#!/usr/bin/python # -*- coding: utf-8 -*- # Author: Zaran import irclib import sys class MatchState: gametypes = { 'duel':2, 'ctf':8, 'ictf':8, 'ca':8 } def __init__(self): state = {} for gt in MatchState.gametypes: state[gt] = set() self._state = state def __str__(self): matchlist = [ "{}: {}/{}".format(k, len(v), self.__class__.gametypes[k]) for k,v in self._state.items() ] return "|".join(matchlist) def _remove_from_gametype(self, nickname, gametype): if gametype in self._state: self._state[gametype].discard(nickname) def _add_to_gametype(self, nickname, gametype): """Internal: add a nickname to a given gametype""" if gametype in self._state: self._state[gametype].add(nickname) def add(self,nickname,gametypes=None): """Add a nickname to a list of gametypes or to all gametypes if the list is not specified""" if (gametypes is None) or (len(gametypes) == 0): for gt in self._state: self._add_to_gametype(nickname,gt) else: for gt in gametypes: self._add_to_gametype(nickname,gt) def remove(self,nickname,gametypes=None): if (gametypes is None) or (len(gametypes) == 0): for gt in self._state: self._remove_from_gametype(nickname,gt) else: for gt in gametypes: self._remove_from_gametype(nickname,gt) def rename(self, oldnick, newnick): for pl in self._state.values(): if oldnick in pl: pl.remove(oldnick) pl.add(newnick) def player_list(self,gametypes=None): result = {} if (gametypes is None) or (len(gametypes) == 0): for gt in self._state: result[gt] = list(self._state[gt]) else: for gt in gametypes: if gt in self._state[gt]: result[gt] = list(self._state[gt]) return result def check_match_begin(self): gametype = None player_list = None for gt in self._state: if len(self._state[gt]) == self.__class__.gametypes[gt]: player_list = list(self._state[gt]) gametype = gt self._state[gt] = set() for player in player_list: self.remove(player) break return gametype, player_list class IRCMatchBot(irclib.SimpleIRCClient): def __init__(self, target): irclib.SimpleIRCClient.__init__(self) self.target = target self.matchState = MatchState() def update_topic(self): """Set the channel topic to the match state""" self.connection.topic(self.target, str(self.matchState)) def on_welcome(self, connection, event): connection.join(self.target) def on_join(self, connection, event): pass def on_mode(self, connection, event): if connection.get_nickname() in event.arguments(): self.update_topic() def on_pubmsg(self, connection, event): nick = irclib.nm_to_n(event.source()) words = event.arguments()[0].split(None,1) command = words[0] if command[0] == '!': command = command[1:] if (len(words) > 1) and (len(words[1]) > 0): args = words[1] else: args = None self.do_command(connection,nick,command,args) def do_command(self, c, nick, command, args): if command == "help": c.privmsg(nick, "Je suis le bot de Pickup de #warsow.fr") c.privmsg(nick, "") elif (command == "add") or (command == "remove") or (command == "list"): if args is None: gtlist = None else: gtlist = [gt.strip() for gt in args.split(',')] if command == "add": self.matchState.add(nick, gtlist) gametype, player_list = self.matchState.check_match_begin() if gametype is not None: c.privmsg( self.target, "Un {} est sur le point de commencer. Liste des joueurs : {}" .format( gametype, ", ".join(player_list) ) ) self.update_topic() elif command == "remove": self.matchState.remove(nick, gtlist) self.update_topic() elif command == "list": result = self.matchState.player_list(gtlist) for gt in result: if len(result[gt]) > 0: c.privmsg(nick, "{}: {}".format(gt, ", ".join(result[gt]))) else: c.privmsg(nick, "Cette commande n'existe pas, tape !help pour obtenir de l'aide") def on_part(self, c, e): nick = irclib.nm_to_n(e.source()) self.matchState.remove(nick, None) self.update_topic() def on_quit(self, c, e): self.on_part(c,e) def on_disconnect(self, connection, event): sys.exit(0) def on_nick(self,c,e): old_nick = irclib.nm_to_n(e.source()) new_nick = e.target() self.matchState.rename(old_nick, new_nick) def main(): if len(sys.argv) != 4: print "Usage: " + sys.argv[0] + " " sys.exit(1) s = sys.argv[1].split(":", 1) server = s[0] if len(s) == 2: try: port = int(s[1]) except ValueError: print "Error: Erroneous port." sys.exit(1) else: port = 6667 nickname = sys.argv[2] channel = sys.argv[3] c = IRCMatchBot(channel) try: c.connect(server, port, nickname) except irclib.ServerConnectionError, x: print x sys.exit(1) c.start() if __name__ == "__main__": main()