# Twitch IRC status autoupdate # Create an empty file called config.yml in the same directory, containing: # host: irc.quakenet.org # port: 6667 # channels: ["#channel", "#anotherchannel"] # nspass: "nickserv/Q password" # password: "server password for BNC or private server" # twitch: "channelname" import requests import yaml from HTMLParser import HTMLParser from sys import stdout from twisted.internet import reactor, task, protocol from twisted.python import log from twisted.words.protocols import irc from twisted.application import internet, service with open('config.yml') as f: config = yaml.load(f.read()) HOST, PORT = config['host'], config['port'] def munge(inp): # Prevents highlight notification in most clients return inp[0] + u"\u200b" + inp[1:] class TwitchProtocol(irc.IRCClient): password = config["password"] if "password" in config else None nickname = 'Twitch' username = 'Twitch' versionName = 'Twitch' versionNum = 'v1.0' realname = 'by blha303. https://gist.github.com/blha303' loopcall = None status = False def signedOn(self): for channel in self.factory.channels: self.join(channel) #Quakenet self._send_message("auth %s %s" % (self.nickname, config["nspass"]), "Q") #Nickserv self._send_message("identify %s %s" % (self.nickname, config["nspass"]), "NickServ") #Nickserv that doesn't support specifying a nickname self._send_message("identify %s" % config["nspass"], "NickServ") def restartloop(reason): reason.printTraceback() print "Loop crashed: " + reason.getErrorMessage() self.loopcall.start(5.0).addErrback(restartloop) self.loopcall = task.LoopingCall(self.getTwitchStatus) self.loopcall.start(5.0).addErrback(restartloop) def getTwitchStatus(self): channel = config["twitch"] data = requests.get("http://api.justin.tv/api/stream/list.json?channel=" + channel).json() if data and not self.status: fmt = "{}: {} {} ({})" self.status = True title = data[0]['title'] playing = ("playing " + data[0]['meta_game']) if "meta_game" in data[0] else "" viewers = "\x033\x02Online now!\x02\x0f " + str(data[0]["channel_count"]) + " viewer" print viewers viewers = viewers + "s" if not " 1 view" in viewers else viewers print viewers h = HTMLParser() for ch in self.factory.channels: self._send_message(h.unescape(fmt.format(title, munge(channel), playing, viewers)), ch) elif not data and self.status: self.status = False for ch in self.factory.channels: self._send_message("%s is now offline." % channel, ch) def privmsg(self, user, channel, message): nick, _, host = user.partition('!') print "<%s> %s" % (nick, message) def _send_message(self, msg, target, nick=None): if nick: msg = '%s, %s' % (nick, msg) self.msg(target, msg) print "<%s> %s" % (self.nickname, msg) class TwitchFactory(protocol.ReconnectingClientFactory): protocol = TwitchProtocol channels = config["channels"] if __name__ == '__main__': reactor.connectTCP(HOST, PORT, TwitchFactory()) log.startLogging(stdout) reactor.run() elif __name__ == '__builtin__': application = service.Application('Twitch') ircService = internet.TCPClient(HOST, PORT, TwitchFactory()) ircService.setServiceParent(application)