Last active 1652358075

Python IRC bot for automatically retrieving Twitch stream status

Steven Smith revised this gist 1386596818. Go to revision

1 file changed, 3 insertions, 8 deletions

irctwitch.py

@@ -22,11 +22,6 @@ with open('config.yml') as f:
22 22 HOST, PORT = config['host'], config['port']
23 23
24 24
25 - def munge(inp):
26 - # Prevents highlight notification in most clients
27 - return inp[0] + u"\u200b" + inp[1:]
28 -
29 -
30 25 class TwitchProtocol(irc.IRCClient):
31 26 password = config["password"] if "password" in config else None
32 27 nickname = 'Twitch'
@@ -44,9 +39,9 @@ class TwitchProtocol(irc.IRCClient):
44 39 #Quakenet
45 40 self._send_message("auth %s %s" % (self.nickname, config["nspass"]), "Q")
46 41 #Nickserv
47 - self._send_message("identify %s %s" % (self.nickname, config["nspass"]), "NickServ")
42 + #self._send_message("identify %s %s" % (self.nickname, config["nspass"]), "NickServ")
48 43 #Nickserv that doesn't support specifying a nickname
49 - self._send_message("identify %s" % config["nspass"], "NickServ")
44 + #self._send_message("identify %s" % config["nspass"], "NickServ")
50 45
51 46 def restartloop(reason):
52 47 reason.printTraceback()
@@ -69,7 +64,7 @@ class TwitchProtocol(irc.IRCClient):
69 64 print viewers
70 65 h = HTMLParser()
71 66 for ch in self.factory.channels:
72 - self._send_message(h.unescape(fmt.format(title, munge(channel), playing, viewers)), ch)
67 + self._send_message(h.unescape(fmt.format(title, channel, playing, viewers)), ch)
73 68 elif not data and self.status:
74 69 self.status = False
75 70 for ch in self.factory.channels:

Steven Smith revised this gist 1383737068. Go to revision

1 file changed, 103 insertions

irctwitch.py(file created)

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