Last active 1652358075

Python IRC bot for automatically retrieving Twitch stream status

irctwitch.py Raw
1# Twitch IRC status autoupdate
2# Create an empty file called config.yml in the same directory, containing:
3# host: irc.quakenet.org
4# port: 6667
5# channels: ["#channel", "#anotherchannel"]
6# nspass: "nickserv/Q password"
7# password: "server password for BNC or private server"
8# twitch: "channelname"
9
10import requests
11import yaml
12from HTMLParser import HTMLParser
13from sys import stdout
14
15from twisted.internet import reactor, task, protocol
16from twisted.python import log
17from twisted.words.protocols import irc
18from twisted.application import internet, service
19
20with open('config.yml') as f:
21 config = yaml.load(f.read())
22HOST, PORT = config['host'], config['port']
23
24
25class TwitchProtocol(irc.IRCClient):
26 password = config["password"] if "password" in config else None
27 nickname = 'Twitch'
28 username = 'Twitch'
29 versionName = 'Twitch'
30 versionNum = 'v1.0'
31 realname = 'by blha303. https://gist.github.com/blha303'
32 loopcall = None
33 status = False
34
35
36 def signedOn(self):
37 for channel in self.factory.channels:
38 self.join(channel)
39 #Quakenet
40 self._send_message("auth %s %s" % (self.nickname, config["nspass"]), "Q")
41 #Nickserv
42 #self._send_message("identify %s %s" % (self.nickname, config["nspass"]), "NickServ")
43 #Nickserv that doesn't support specifying a nickname
44 #self._send_message("identify %s" % config["nspass"], "NickServ")
45
46 def restartloop(reason):
47 reason.printTraceback()
48 print "Loop crashed: " + reason.getErrorMessage()
49 self.loopcall.start(5.0).addErrback(restartloop)
50 self.loopcall = task.LoopingCall(self.getTwitchStatus)
51 self.loopcall.start(5.0).addErrback(restartloop)
52
53 def getTwitchStatus(self):
54 channel = config["twitch"]
55 data = requests.get("http://api.justin.tv/api/stream/list.json?channel=" + channel).json()
56 if data and not self.status:
57 fmt = "{}: {} {} ({})"
58 self.status = True
59 title = data[0]['title']
60 playing = ("playing " + data[0]['meta_game']) if "meta_game" in data[0] else ""
61 viewers = "\x033\x02Online now!\x02\x0f " + str(data[0]["channel_count"]) + " viewer"
62 print viewers
63 viewers = viewers + "s" if not " 1 view" in viewers else viewers
64 print viewers
65 h = HTMLParser()
66 for ch in self.factory.channels:
67 self._send_message(h.unescape(fmt.format(title, channel, playing, viewers)), ch)
68 elif not data and self.status:
69 self.status = False
70 for ch in self.factory.channels:
71 self._send_message("%s is now offline." % channel, ch)
72
73
74 def privmsg(self, user, channel, message):
75 nick, _, host = user.partition('!')
76 print "<%s> %s" % (nick, message)
77
78
79 def _send_message(self, msg, target, nick=None):
80 if nick:
81 msg = '%s, %s' % (nick, msg)
82 self.msg(target, msg)
83 print "<%s> %s" % (self.nickname, msg)
84
85
86class TwitchFactory(protocol.ReconnectingClientFactory):
87 protocol = TwitchProtocol
88 channels = config["channels"]
89
90if __name__ == '__main__':
91 reactor.connectTCP(HOST, PORT, TwitchFactory())
92 log.startLogging(stdout)
93 reactor.run()
94
95elif __name__ == '__builtin__':
96 application = service.Application('Twitch')
97 ircService = internet.TCPClient(HOST, PORT, TwitchFactory())
98 ircService.setServiceParent(application)
99