-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathirc.py
157 lines (135 loc) · 5.68 KB
/
irc.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
import socket
from ConfigParser import SafeConfigParser
import traceback
import pygame
from gui import CommandsGUI
class TwitchIRCBot(object):
def __init__(self, config):
""" Inspired by /~https://github.com/Abysice/TwitchIRCBot/blob/master/Twitch.py.
Connects to Twitch IRC on a channel, using the account and oauth token provided."""
#Config
self.host = "irc.twitch.tv"
self.port = 6667
self.nickname = self.ident = config.get('Twitch', 'account')
self.oauth = config.get('Twitch', 'oauth') # use http://twitchapps.com/tmi/ to generate
self.real_name = config.get('Twitch', 'real_name') # This doesn't really matter.
self.channel = "#" + self.nickname.lower()
self.socket = None
self.readbuffer = ""
with open('blacklist') as blackfile:
self.blacklist = blackfile.readlines()
with open('censorlist') as censorfile:
self.censored = censorfile.readlines()
def connect(self):
print "Connecting..."
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.connect((self.host, self.port))
self.socket.setblocking(0)
print "Sending Connection info"
self.socket.send("PASS %s\r\n" % self.oauth) # Send the token before the username, for some reason
# Send the rest of the login data and join the channel
self.socket.send("NICK %s\r\n" % self.nickname)
self.socket.send("USER %s %s :%s\r\n" % (self.ident, self.host, self.real_name))
self.socket.send("JOIN %s\r\n" % self.channel)
def consume(self):
try:
bytes_in = self.socket.recv(1024)
except socket.error, e:
errno, msg = e.args
if errno != 10035:
print "Socket error during read: %s" % e
print " [X] Connection lost, reconnecting"
self.socket.close()
self.connect()
else:
# print bytes_in,
if bytes_in == '':
print " [X] Received empty string, did i lose my connection? Reconnecting"
self.socket.close()
self.connect()
self.readbuffer += bytes_in
# Split the buffer into lines
lines = self.readbuffer.split('\r\n')
# Pop leftovers back on the buffer
if self.readbuffer.endswith('\r\n'):
self.readbuffer = ""
else:
self.readbuffer = lines[-1]
lines.pop()
for line in lines:
if not line:
continue
elif line.startswith('PING'):
print "Received ping: %s" % line
answer = "PONG%s" % ("".join(line.split("PING")[1:]), )
print "Answering %s" % (answer, )
self.socket.sendall(answer)
else:
self.consume_line(line)
def consume_line(self, line):
prefix, command, args = self.parsemsg(line)
if command == 'PRIVMSG':
#Prefix looks like user!user@user.twitch.tv, so grab the firs instance
if '!' in prefix:
user = prefix.split('!')[0]
if user != 'jtv': # Ignore jtv, he's a jerk
tokens = args[1] if len(args) >= 1 else ''
if tokens:
for blacktoken in self.censored:
if blacktoken.strip().lower() in tokens:
print "Banning user %s for saying %s" % (user, blacktoken)
return self.ban(user)
self.consume_tokens(user, tokens)
else:
print "Invalid prefix %s in line %s" % (prefix, line, )
elif command == 'PING':
self.socket.send('PONG %s' % args)
elif command == "JOIN":
if args:
user = prefix.split('!')[0].strip().strip('#')
for blacktoken in self.blacklist:
if blacktoken.strip().lower() in user.lower():
print "Banning user %s because it contains %s" % (user, blacktoken)
return self.ban(user) # Breaks the loop
def consume_tokens(self, user, tokens):
try:
pygame.event.post(pygame.event.Event(pygame.USEREVENT + 1, user=user, tokens=tokens))
except Exception, e:
print " [X] Error processing tokens %s: %s" % (tokens, e, )
def parsemsg(self, s):
"""Breaks a message from an IRC server into its prefix, command, and arguments.
Shamelessly ripped from twisted's IRC implementation
"""
prefix = ''
trailing = []
if s[0] == ':':
prefix, s = s[1:].split(' ', 1)
if s.find(' :') != -1:
s, trailing = s.split(' :', 1)
args = s.split()
args.append(trailing)
else:
args = s.split()
command = args.pop(0)
return prefix, command, args
def ban(self, user):
self.socket.sendall(".ban %s" % user)
def main():
# fmt = "%(asctime)s: %(message)s"
# logging.basicConfig(filename='twitch.log', level=logging.DEBUG, format=fmt)
config = SafeConfigParser()
config.read("twitch.conf")
game = CommandsGUI()
bot = TwitchIRCBot(config)
bot.connect()
while True:
bot.consume()
game.update()
if __name__ == "__main__":
try:
main()
except Exception, e:
print traceback.format_exc()
print "Woops, something went wrong, please send me a screenshot of this error up there"
print "Then press enter to close the program"
raw_input()