From 18e333a8c3f401e97489ffc712adab27a4a2e0c4 Mon Sep 17 00:00:00 2001 From: Zaran Date: Sun, 27 Nov 2011 01:57:06 -0800 Subject: Initial commit --- main.py | 186 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 main.py (limited to 'main.py') diff --git a/main.py b/main.py new file mode 100644 index 0000000..1994135 --- /dev/null +++ b/main.py @@ -0,0 +1,186 @@ +#!/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() -- cgit v1.2.3-70-g09d2