Advertisement
Guest User

Untitled

a guest
Dec 23rd, 2013
109
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.33 KB | None | 0 0
  1. # Copyright (c) Mathias Kaerlev 2011-2012.
  2.  
  3. from twisted.words.protocols import irc
  4. from twisted.internet import reactor, protocol
  5. from pyspades.constants import MAX_CHAT_SIZE
  6. from pyspades.common import encode, decode
  7. from pyspades.types import AttributeSet
  8. import commands
  9.  
  10. import random
  11. import string
  12. from itertools import groupby, chain, izip
  13. from operator import attrgetter
  14.  
  15. MAX_IRC_CHAT_SIZE = MAX_CHAT_SIZE * 2
  16. PRINTABLE_CHARACTERS = ('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP'
  17. 'QRSTUVWXYZ!"#$%&\\\'()*+,-./:;<=>?@[\\]^_`{|}~ \t')
  18. IRC_TEAM_COLORS = {0 : '\x0302', 1 : '\x0303'}
  19. SPLIT_WHO_IN_TEAMS = True
  20. SPLIT_THRESHOLD = 20 # players
  21.  
  22. def is_printable(value):
  23. return value in PRINTABLE_CHARACTERS
  24.  
  25. def filter_printable(value):
  26. return filter(is_printable, value)
  27.  
  28. def channel(func):
  29. def new_func(self, user, channel, *arg, **kw):
  30. if not channel.lower() == self.factory.channel:
  31. return
  32. user = user.split('!', 1)[0]
  33. func(self, user, channel, *arg, **kw)
  34. return new_func
  35.  
  36. class IRCBot(irc.IRCClient):
  37. ops = None
  38. voices = None
  39. unaliased_name = None
  40.  
  41. def _get_nickname(self):
  42. return self.factory.nickname
  43. nickname = property(_get_nickname)
  44.  
  45. def _get_colors(self):
  46. return self.factory.colors
  47. colors = property(_get_colors)
  48.  
  49. def _get_admin(self):
  50. return self.factory.admin
  51. admin = property(_get_admin)
  52.  
  53. def _get_user_types(self):
  54. return self.factory.user_types
  55. user_types = property(_get_user_types)
  56.  
  57. def _get_rights(self):
  58. return self.factory.rights
  59. rights = property(_get_rights)
  60.  
  61. def signedOn(self):
  62. self.join(self.factory.channel, self.factory.password)
  63.  
  64. def joined(self, channel):
  65. if channel.lower() == self.factory.channel:
  66. self.ops = set()
  67. self.voices = set()
  68. print "Joined channel %s" % channel
  69.  
  70. def irc_NICK(self, prefix, params):
  71. user = prefix.split('!', 1)[0]
  72. new_user = params[0]
  73. if user in self.ops:
  74. self.ops.discard(user)
  75. self.ops.add(new_user)
  76. if user in self.voices:
  77. self.voices.discard(user)
  78. self.voices.add(new_user)
  79.  
  80. def irc_RPL_NAMREPLY(self, *arg):
  81. if not arg[1][2].lower() == self.factory.channel:
  82. return
  83. for name in arg[1][3].split():
  84. mode = name[0]
  85. l = {'@': self.ops, '~': self.ops, '&': self.ops, '+': self.voices, '%': self.voices}
  86. if mode in l:
  87. l[mode].add(name[:])
  88.  
  89. def left(self, channel):
  90. if channel.lower() == self.factory.channel:
  91. self.ops = None
  92. self.voices = None
  93.  
  94. @channel
  95. def modeChanged(self, user, channel, set, modes, args):
  96. ll = {'o' : self.ops, 'q' : self.ops, 'a' : self.ops, 'v' : self.voices, 'h' : self.voices}
  97. for i in range(len(args)):
  98. mode, name = modes[i], args[i]
  99. if mode not in ll:
  100. continue
  101. l = ll[mode]
  102. if set:
  103. l.add(name)
  104. elif not set:
  105. l.discard(name)
  106.  
  107. @channel
  108. def privmsg(self, user, channel, msg):
  109. if user in self.ops or user in self.voices:
  110. if user in self.ops and user == 1['@']:
  111. prefix = '@'
  112. else:
  113. prefix = '+'
  114. alias = self.factory.aliases.get(user, user)
  115. if msg.startswith(self.factory.commandprefix) and user in self.ops:
  116. self.unaliased_name = user
  117. self.name = prefix + alias
  118. input = msg[len(self.factory.commandprefix):]
  119. result = commands.handle_input(self, input)
  120. if result is not None:
  121. self.send("%s: %s" % (user, result))
  122. elif msg.startswith(self.factory.chatprefix):
  123. max_len = MAX_IRC_CHAT_SIZE - len(self.protocol.server_prefix) - 1
  124. msg = msg[len(self.factory.chatprefix):].strip()
  125. message = ("<%s> %s" % (prefix + alias, msg))[:max_len]
  126. message = message.decode('cp1252')
  127. print message.encode('ascii', 'replace')
  128. self.factory.server.send_chat(encode(message))
  129.  
  130. @channel
  131. def userLeft(self, user, channel):
  132. self.ops.discard(user)
  133. self.voices.discard(user)
  134.  
  135. def userQuit(self, user, message):
  136. self.userLeft(user, self.factory.channel)
  137.  
  138. def userKicked(self, kickee, channel, kicker, message):
  139. self.userLeft(kickee, channel)
  140.  
  141. def send(self, msg, filter = False):
  142. msg = msg.encode('cp1252', 'replace')
  143. if filter:
  144. msg = filter_printable(msg)
  145. self.msg(self.factory.channel, msg)
  146.  
  147. def me(self, msg, filter = False):
  148. msg = msg.encode('cp1252', 'replace')
  149. if filter:
  150. msg = filter_printable(msg)
  151. self.describe(self.factory.channel, msg)
  152.  
  153. class IRCClientFactory(protocol.ClientFactory):
  154. protocol = IRCBot
  155. lost_reconnect_delay = 20
  156. failed_reconnect_delay = 60
  157. bot = None
  158. aliases = None
  159. colors = True
  160. admin = None
  161. user_types = None
  162. rights = None
  163.  
  164. def __init__(self, server, config):
  165. self.aliases = {}
  166. self.admin = True
  167. self.user_types = AttributeSet(['admin', 'irc'])
  168. self.rights = AttributeSet()
  169. for user_type in self.user_types:
  170. self.rights.update(commands.rights.get(user_type, ()))
  171. self.server = server
  172. self.nickname = config.get('nickname',
  173. 'pyspades%s' % random.randrange(0, 99)).encode('ascii')
  174. self.username = config.get('username', 'pyspades').encode('ascii')
  175. self.realname = config.get('realname', server.name).encode('ascii')
  176. self.channel = config.get('channel', "#pyspades.bots").encode(
  177. 'ascii').lower()
  178. self.commandprefix = config.get('commandprefix', '.').encode('ascii')
  179. self.chatprefix = config.get('chatprefix', '').encode('ascii')
  180. self.password = config.get('password', '').encode('ascii') or None
  181.  
  182. def startedConnecting(self, connector):
  183. print "Connecting to IRC server..."
  184.  
  185. def clientConnectionLost(self, connector, reason):
  186. print "Lost connection to IRC server (%s), reconnecting in %s seconds" % (
  187. reason, self.lost_reconnect_delay)
  188. reactor.callLater(self.lost_reconnect_delay, connector.connect)
  189.  
  190. def clientConnectionFailed(self, connector, reason):
  191. print "Could not connect to IRC server (%s), retrying in %s seconds" % (
  192. reason, self.failed_reconnect_delay)
  193. reactor.callLater(self.failed_reconnect_delay, connector.connect)
  194.  
  195. def buildProtocol(self, address):
  196. p = self.protocol()
  197. p.factory = self
  198. p.protocol = self.server
  199. self.bot = p
  200. return p
  201.  
  202. class IRCRelay(object):
  203. factory = None
  204.  
  205. def __init__(self, protocol, config):
  206. self.factory = IRCClientFactory(protocol, config)
  207. protocol.connectTCP(config.get('server'), config.get('port', 6667),
  208. self.factory)
  209.  
  210. def send(self, *arg, **kw):
  211. if self.factory.bot is None:
  212. return
  213. self.factory.bot.send(*arg, **kw)
  214.  
  215. def me(self, *arg, **kw):
  216. if self.factory.bot is None:
  217. return
  218. self.factory.bot.me(*arg, **kw)
  219.  
  220. def format_name(player):
  221. return '%s #%s' % (player.name, player.player_id)
  222.  
  223. def format_name_color(player):
  224. return (IRC_TEAM_COLORS.get(player.team.id, '') +
  225. '%s #%s' % (player.name, player.player_id))
  226.  
  227. def irc(func):
  228. return commands.restrict(func, 'irc')
  229.  
  230. @irc
  231. def who(connection):
  232. protocol = connection.protocol
  233. player_count = len(protocol.players)
  234. if player_count == 0:
  235. connection.me('has no players connected')
  236. return
  237. sorted_players = sorted(protocol.players.values(),
  238. key = attrgetter('team.id', 'name'))
  239. name_formatter = format_name_color if connection.colors else format_name
  240. teams = []
  241. formatted_names = []
  242. for k, g in groupby(sorted_players, attrgetter('team')):
  243. teams.append(k)
  244. formatted_names.append(map(name_formatter, g))
  245. separator = '\x0f, ' if connection.colors else ', '
  246. if not SPLIT_WHO_IN_TEAMS or player_count < SPLIT_THRESHOLD:
  247. noun = 'player' if player_count == 1 else 'players'
  248. msg = 'has %s %s connected: ' % (player_count, noun)
  249. msg += separator.join(chain.from_iterable(formatted_names))
  250. connection.me(msg)
  251. else:
  252. for team, names in izip(teams, formatted_names):
  253. name_count = len(names)
  254. noun = 'player' if name_count == 1 else 'players'
  255. msg = 'has %s %s in %s: ' % (name_count, noun, team.name)
  256. msg += separator.join(names)
  257. connection.me(msg)
  258.  
  259. @irc
  260. def score(connection):
  261. connection.me("scores: Blue %s - Green %s" % (
  262. connection.protocol.blue_team.score,
  263. connection.protocol.green_team.score))
  264.  
  265. @irc
  266. def alias(connection, value = None):
  267. aliases = connection.factory.aliases
  268. unaliased_name = connection.unaliased_name
  269. if value is None:
  270. alias = aliases.get(unaliased_name)
  271. if alias:
  272. message = 'aliases %s to %s' % (unaliased_name, alias)
  273. else:
  274. message = "doesn't have an alias for %s" % unaliased_name
  275. else:
  276. aliases[unaliased_name] = value
  277. message = 'will alias %s to %s' % (unaliased_name, value)
  278. connection.me(message)
  279.  
  280. @irc
  281. def unalias(connection):
  282. aliases = connection.factory.aliases
  283. unaliased_name = connection.unaliased_name
  284. if unaliased_name in aliases:
  285. aliases.pop(unaliased_name)
  286. message = 'will no longer alias %s' % unaliased_name
  287. else:
  288. message = "doesn't have an alias for %s" % unaliased_name
  289. connection.me(message)
  290.  
  291. @irc
  292. def colors(connection):
  293. connection.colors = not connection.colors
  294. if connection.colors:
  295. return '\x0312c\x0304o\x0309l\x0308o\x0306r\x0313s \x0f\x16ON!'
  296. else:
  297. return 'colors off'
  298.  
  299. for func in (who, score, alias, unalias, colors):
  300. commands.add(func)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement