Example #1
0
    def __init__(self, networkname, server_config, bot_config, joinlist,
                 modules_config):
        self.alive = True
        self.connected = False
        self.hostname = server_config['hostname']
        self.port = int(server_config.get('port', "6667"))
        self.nick = bot_config['nick']
        self.altnick = bot_config.get('altnick', self.nick + "_")
        self.username = bot_config['username']
        self.realname = bot_config['realname']
        self.owner = bot_config['owner']
        self.networkname = networkname

        self.joinlist = joinlist

        self._reader_thread = None
        self._parser = MessageParser()
        self._init_callback_table()
        self._socket = None

        self._channel_list = []

        self._modules_config = modules_config
        self.dynamic_modules = [
            DynamicModule(self, m, c) for m, c in modules_config.items()
        ]

        self._last_ping = time.time()
Example #2
0
    def __init__(self, networkname, server_config, bot_config, joinlist, modules_config):
        self.alive = True
        self.connected = False
        self.hostname = server_config['hostname']
        self.port = int(server_config.get('port', "6667"))
        self.nick = bot_config['nick']
        self.altnick = bot_config.get('altnick', self.nick + "_")
        self.username = bot_config['username']
        self.realname = bot_config['realname']
        self.owner = bot_config['owner']
        self.networkname = networkname

        self.joinlist = joinlist

        self._reader_thread = None
        self._parser = MessageParser()
        self._init_callback_table()
        self._socket = None

        self._channel_list = []

        self._modules_config = modules_config
        self.dynamic_modules = [DynamicModule(self, m, c) for m, c in modules_config.items()]

        self._last_ping = time.time()
Example #3
0
    def __init__(self, sock):
        self.__socket = sock
        self.__message_parser = MessageParser()
        self.__lobby_model = LobbyModel()
        # name of the game
        self.__game = None
        # player number (1 or 2)
        self.__player = None
        # player id lol
        self.__id = self.__get_own_player_id()
        # add client as player
        self.__lobby_model.add_player(self.__id)

        # register callbacks
        self.__lobby_model.register_callback(LobbyEvent.on_update,
                                             self.on_update_lobby)
        self.__lobby_model.register_callback(LobbyEvent.on_chat, self.on_chat)
Example #4
0
    def __init__(self, message):
        self.message_parser = MessageParser(message)
        # hole, [['2c', '2d'],...] for 6 players
        self.hole = self.message_parser.hole
        # board ['2c', '2d', '2h', ...] for at most 5 board cards
        self.board = self.message_parser.board
        self.viewing_player = self.message_parser.get_position()
        self.betting_string = self.message_parser.get_betting_string(rd=None)
        self.board_string = self.message_parser.get_board_string(rd=None)
        # a two-dimension list, dim-1 is round, dim-2 is i-th action of a round
        self.betting_action = self.get_betting_action()
        # a one-dimension list, store each {action string} as an element
        self.action_list = []
        # store each {action object} of all round actions in a one-dimension list
        for each_round_action in self.betting_action:
            for action in each_round_action:
                self.action_list.append(Action(action))
        # set up basic data structure
        self.spent = [50, 100, 0, 0, 0, 0]
        self.active = [True] * 6
        self.fold = [False] * 6
        self.allin = [False] * 6
        self.pot = 150
        self.max_bet = 100

        self.current_player = 2  # player at seat 2 is first player to act in PREFLOP round
        self.finished = False
        self.round = Round.PREFLOP
        self.boards = None  # first round have no board cards
        self.holes = None  # hole array for 6 players
        self.min_no_limit_raise_to = 2 * 100
        self.max_no_limit_raise_to = 20000

        self.next_round_flag = False

        self.call_number = 0

        # update [hole] and [board]
        self.holes = self.message_parser.get_hole_card(position=None)
        self.boards = self.message_parser.get_board_card(rd=None)

        # after setting up basic data structure, start to do each action and update data structure
        cnt = 0
        for action in self.action_list:
            cnt += 1
            self.do_action(action)
    def __init__(self, roverID, blockInfo):
        self.roverID = roverID
        self.blockInfo = blockInfo
        self.posY = 0
        self.nextY = 0
        if roverID == 0:
            self.posX = 0
            self.nextX = 0
        else:
            self.posX = -1
            self.nextX = -1

        # Declare test client and parser
        self.clientConnection = TestClient()
        self.parser = MessageParser(roverID)

        # Connect signals and slots
        self.clientConnection.messageFromServer.connect(self.parser.parse)
        self.parser.parsedMessageSignal.connect(self.messageFromServer)
        self.parser.constructedMessageSignal.connect(
            self.clientConnection.sendMessageToServer)
Example #6
0
    def __init__(self, sock):
        self.__socket = sock
        self.__message_parser = MessageParser()
        self.__lobby_model = LobbyModel()
        # name of the game
        self.__game = None
        # player number (1 or 2)
        self.__player = None
        # player id lol
        self.__id = self.__get_own_player_id()
        # add client as player
        self.__lobby_model.add_player(self.__id)

        # register callbacks
        self.__lobby_model.register_callback(LobbyEvent.on_update, self.on_update_lobby)
        self.__lobby_model.register_callback(LobbyEvent.on_chat, self.on_chat)

def cleanup():
    print('cleanup')
    server.closeServer()


# Make Qt happy
app = QApplication(sys.argv)

# Declare server
server = team13Server('192.168.42.1', 2000)
# Declare server GUI
serverGui = MainWindow()
# Declare parser for rover 0
rover0Parser = MessageParser(0)
# Declare parser for rover 1
rover1Parser = MessageParser(1)
# Central class holding positions of both rovers
roverPositions = RoverPositions()
# Declare controller for rover 0
rover0Controller = Rover0Control(roverPositions)
# Declare controller for rover 1
rover1Controller = Rover1Control(roverPositions)

# Connect server signals
server.client0Message.connect(rover0Parser.parse)
server.client1Message.connect(rover1Parser.parse)
server.serverClosed.connect(rover0Parser.closeLog)
server.startSelf.connect(server.runServer)
# Connect GUI signals
Example #8
0
# Please install the slackclient module either globally or into ./lib before running this bot
# Additionally, you should fill in the config.json with all of the appropriate keys, tokens, and IDs

import json, sys, socket, time
sys.path.insert(0, 'lib')
sys.dont_write_bytecode = True

from rtmctl import SlackBotController
from messageparser import MessageParser

with open('config.json', 'r') as cfg:
    config = json.load(cfg)

slackbot = SlackBotController(config=config, parser=MessageParser(config))


# Runs the bot and handles/retries on connection errors,
# implements an exponential backoff up to 256 seconds.
def retryLoop(func, sec):
    try:
        func()
    except Exception, e:
        sec = sec + 1 if sec < 8 else 1
        print 'Connection error, retrying in ' + str(2**sec) + ' seconds...'
        time.sleep(2**sec)
        retryLoop(func, sec)


retryLoop(slackbot.run, 0)
from messageparser import MessageParser

mp = MessageParser()

try:
    prefix, command, params = mp.parseMessage('USER oskar oskar 127.0.0.1 :realname\r\n')
except ValueError as e:
    print(e)

print("prefix: ", prefix)
print("command:", command)
print("parameters:", params)

# try:
#     mp.parseMessage(':prefix 001 middle :this is a trailing parameter \r\n')
# except ValueError as e:
#     print(e)

# print("prefix: ", mp.prefix)
# print("command:", mp.command)
# print("parameters:", mp.parameters)
Example #10
0
class ServerConnection(object):
    """
    Class handling irc servers.
    """
    PING_INTERVAL_THRESHOLD = 300  # 300 seconds

    def __init__(self, networkname, server_config, bot_config, joinlist,
                 modules_config):
        self.alive = True
        self.connected = False
        self.hostname = server_config['hostname']
        self.port = int(server_config.get('port', "6667"))
        self.nick = bot_config['nick']
        self.altnick = bot_config.get('altnick', self.nick + "_")
        self.username = bot_config['username']
        self.realname = bot_config['realname']
        self.owner = bot_config['owner']
        self.networkname = networkname

        self.joinlist = joinlist

        self._reader_thread = None
        self._parser = MessageParser()
        self._init_callback_table()
        self._socket = None

        self._channel_list = []

        self._modules_config = modules_config
        self.dynamic_modules = [
            DynamicModule(self, m, c) for m, c in modules_config.items()
        ]

        self._last_ping = time.time()

    def _init_callback_table(self):
        self._receive_callbacks = {
            MessageType.PRIVATE_MESSAGE: self._private_message_received,
            MessageType.JOIN: self._join_received,
            MessageType.PART: self._part_received,
            MessageType.PING: self._ping_received,
            MessageType.QUIT: self._quit_received,
            MessageType.TOPIC: self._topic_received,
            MessageType.END_OF_MOTD: self._motd_received,
            #MessageType.NICK_IN_USE: self.ni,
            MessageType.TOPIC_REPLY: self._topic_reply_received,
            MessageType.USERS: self._users_received,
            MessageType.END_OF_USERS: self._users_end_received,
            MessageType.CHANNEL_MESSAGE: self._channel_message_received,
            MessageType.UNKNOWN: self._unknown_message_received,
            MessageType.CTCP_TIME: self._ctcp_message_received,
            MessageType.CTCP_VERSION: self._ctcp_version_received,
            MessageType.CTCP_PING: self._ctcp_message_received,
            MessageType.CTCP_DCC: self._ctcp_message_received,
        }

    def connect(self):
        """
        Tries to connect to irc server.
        """
        self._reader_thread = Thread(target=self._connection_loop)
        self._reader_thread.start()

    def _connect(self):
        while self.alive:
            try:
                if self._socket:
                    self._socket.close()

                self._socket = socket.socket(socket.AF_INET,
                                             socket.SOCK_STREAM)
                self._socket.connect((self.hostname, self.port))

                self.NICK(self.nick)
                self.USER(self.username, self.realname)

                self._last_ping = time.time()

                break

            except Exception as e:
                self._print_line(str(e) + " " + self.hostname)
                self._print_line("Trying again in 30 seconds.")
                self._sleep(30)

    def _connection_loop(self):
        while self.alive:
            self._connect()
            self._read()

            if not self.alive:
                break

            self._print_line("Trying again in 60 seconds.")
            self._sleep(60)

    def _write(self, message):
        """
        Prints and writes message to server.
        """
        self._print_line(message[:-1])
        self._socket.send(bytearray(message, 'utf-8'))

    def _check_ping_time(self):
        return time.time(
        ) - self._last_ping < ServerConnection.PING_INTERVAL_THRESHOLD

    def _read(self):
        """
        Reads and handles messages.
        """
        self._socket.settimeout(1.0)
        buff = ""
        while self.alive and self._check_ping_time():
            try:
                tmp = self._socket.recv(4096)
            except socket.timeout as e:
                continue
            except socket.error as e:
                self._print_line(str(e))
                break
            except KeyboardInterrupt:
                self.kill()
                return

            if not self.alive:
                break

            if not tmp:
                break

            tmp = tmp.decode('utf-8')

            buff += tmp
            parsed_messages, remainder = self._parser.parse_buffer(buff)
            buff = remainder
            self._handle_messages(parsed_messages)

        self._socket.close()
        self._print_line("Connection closed.")
        self.connected = False

    def _handle_messages(self, messages):
        """
        Handles a list of messages
        """
        for message in messages:
            self._receive_callbacks[message.type](**message.params)

    def _print_line(self, message):
        """
        Prints message with timestamp.
        """
        print(
            time.strftime("%H:%M:%S") + " |" + self.networkname + "| " +
            message)

    def NICK(self, nick):
        """
        Sets user's nick on server.
        """
        self._write("NICK " + nick + "\r\n")

    def USER(self, username, realname):
        """
        Sets username and realname to server on connect.
        """
        self._write("USER " + username + " 0 * :" + realname + "\r\n")

    def PONG(self, message):
        """
        Reply to PING.
        """
        self._write("PONG :" + message + "\r\n")

    def JOIN(self, channel):
        """
        Joins a irc channel.
        """
        self._write("JOIN :" + channel + "\r\n")

    def PART(self, channel, reason=""):
        """
        PARTs from a channel.
        """
        msg = "PART " + channel
        if reason:
            msg += " :" + reason
        self._write(msg + "\r\n")

    def PRIVMSG(self, target, message):
        """
        Sends PRIVMSG to target.
        """
        self._write("PRIVMSG " + target + " :" + message + "\r\n")

    def PING(self, message):
        """
        Sends PING to server.
        """
        self._write("PING " + message + "\r\n")

    def CTCP(self, target, message):
        self.PRIVMSG(target, str("\x01" + message + "\x01"))

    def NOTICE(self, target, message):
        self._write("NOTICE " + target + " :" + message + "\r\n")

    def _on_connect(self):
        """
        Called when connected to the network.
        """
        self.PING(self.hostname)
        self._join_channels()

        for dm in self.dynamic_modules:
            try:
                dm.instance.on_connect()
            except Exception as e:
                print(e)

    def _join_channels(self):
        """
        Joins channels specified in self.joinlist
        """
        for channel in self.joinlist:
            self.JOIN(channel)

    def kill(self):
        """
        Called when the thread is wanted dead.
        """
        self.alive = False
        for m in self.dynamic_modules:
            m.instance.kill()

    def _private_message_received(self, **kw):
        """
        Called when a private message has been received. Prints it
        and calls on_private_message() on DynamicModule instances.
        """
        source = kw['source']
        message = kw['message']
        full_mask = kw['full_mask']
        self._print_line("PRIVATE" + " <" + source + "> " + message)

        for dm in self.dynamic_modules:
            try:
                dm.instance.on_private_message(source, message, full_mask)
            except Exception as e:
                print(e)

    def _channel_message_received(self, **kw):
        """
        Called when a PRIVMSG to a channel has been received. Prints it
        and calls on_channel_message() on DynamicModule instances.
        """

        source = kw['source']
        message = kw['message']
        full_mask = kw['full_mask']
        channel = kw['channel_name']

        self._print_line(channel + " <" + source + "> " + message)

        for dm in self.dynamic_modules:
            try:
                dm.instance.on_channel_message(source, channel, message,
                                               full_mask)
            except Exception as e:
                print(e)

    def _ping_received(self, **kw):
        """
        Called when PING message has been received.
        """

        self._last_ping = time.time()
        message = kw['message']
        self.PONG(message)

    def _motd_received(self, **kw):
        """
        Called when the end of MOTD message
        has been received.
        """
        message = kw['message']

        self._print_line(message)
        if not self.connected:
            self.connected = True
            self._on_connect()

    def _find_channel_by_name(self, channel_name):
        """
        Returns a channel instance from channel_list
        matching channel_name parameter or None.
        """
        for channel in self._channel_list:
            if channel.name == channel_name:
                return channel

    def _add_channel(self, name, user_list):
        """
        Adds a channel to networks channel list.
        """
        if self._find_channel_by_name(name):
            return

        channel = IrcChannel(name, user_list)
        self._channel_list.append(channel)

    def _users_received(self, **kw):
        """
        Called when USERS message is received. Notifies
        channel instance of the users.
        """

        channel_name = kw['channel_name']
        user_list = kw['user_list']

        channel = self._find_channel_by_name(channel_name)
        if not channel:
            self._add_channel(channel_name, user_list)
            return

        channel.users_message(user_list)

    def _users_end_received(self, **kw):
        """
        Called when USERS message's end has been received.
        Notifies the channel instance.
        """

        channel_name = kw['channel_name']

        channel = self._find_channel_by_name(channel_name)
        if not channel:
            # TODO FIX
            self._print_line(
                "REPORT THIS: usersEndReceived, channel not found")
            return

        channel.users_message_end()
        self._print_line("USERS OF " + channel_name)
        self._print_line(" ".join(channel.userlist))

    def _quit_received(self, **kw):
        """
        Called when a QUIT message has been received. Calls
        on_quit() on DynamicModules
        """

        nick = kw['nick']
        full_mask = kw['full_mask']

        for channel in self._channel_list:
            channel.remove_user(nick)

        self._print_line(nick + " has quit.")

        for dm in self.dynamic_modules:
            try:
                dm.instance.on_quit(nick, full_mask)
            except Exception as e:
                print(e)

    def _part_received(self, **kw):
        """
        Called when a PART message has been received. Calls
        on_part() on DynamicModules
        """

        nick = kw['nick']
        channel_name = kw['channel_name']
        full_mask = kw['full_mask']

        channel = self._find_channel_by_name(channel_name)
        if not channel:
            return

        channel.remove_user(nick)

        self._print_line(nick + " has parted " + channel_name)

        for dm in self.dynamic_modules:
            try:
                dm.instance.on_part(nick, channel_name, full_mask)
            except Exception as e:
                print(e)

    def _join_received(self, **kw):
        """
        Called when a JOIN message has been received. Calls
        on_join() on DynamicModules
        """

        nick = kw['nick']
        channel_name = kw['channel_name']
        full_mask = kw['full_mask']

        channel = self._find_channel_by_name(channel_name)
        if channel:
            channel.add_user(nick)

        self._print_line(nick + " has joined " + channel_name)
        for dm in self.dynamic_modules:
            try:
                dm.instance.on_join(nick, channel_name, full_mask)
            except Exception as e:
                print(e)

    def _topic_received(self, **kw):
        """
        Called when topic is changed on a channel. Calls on_topic()
        on DynamicModules
        """

        nick = kw['nick']
        channel_name = kw['channel_name']
        full_mask = kw['full_mask']
        topic = kw['topic']

        channel = self._find_channel_by_name(channel_name)
        if channel:
            channel.topic = topic

        self._print_line(nick + " changed the topic of " + channel_name +
                         " to: " + topic)
        for dm in self.dynamic_modules:
            try:
                dm.instance.on_topic(nick, channel_name, topic, full_mask)
            except Exception as e:
                print(e)

    def _topic_reply_received(self, **kw):
        """
        Called when server responds to client's /topic or server informs
        of the topic on joined channel.
        """

        channel_name = kw['channel_name']
        topic = kw['topic']

        channel = self._find_channel_by_name(channel_name)
        if channel:
            channel.topic = topic

        self._print_line("Topic in " + channel_name + ": " + topic)

    def _ctcp_message_received(self, **kw):
        self._print_line("CTCP: " + str(kw))

    def _ctcp_version_received(self, **kw):
        ":[email protected] NOTICE irckaaja :VERSION ?l? hakkeroi!"
        self.NOTICE(kw['source'], "\x01VERSION irckaaja 0.1.0\x01")

    def _unknown_message_received(self, **kw):
        self._print_line(kw['message'])

    def _sleep(self, seconds):
        """
        Sleeps for seconds unless not self.alive.
        """
        start = time.time()
        while time.time() < start + seconds and self.alive:
            time.sleep(1)
Example #11
0
class ClientHandler:

    def __init__(self, sock):
        self.__socket = sock
        self.__message_parser = MessageParser()
        self.__lobby_model = LobbyModel()
        # name of the game
        self.__game = None
        # player number (1 or 2)
        self.__player = None
        # player id lol
        self.__id = self.__get_own_player_id()
        # add client as player
        self.__lobby_model.add_player(self.__id)

        # register callbacks
        self.__lobby_model.register_callback(LobbyEvent.on_update, self.on_update_lobby)
        self.__lobby_model.register_callback(LobbyEvent.on_chat, self.on_chat)

    def handle(self):
        logging.info("Client {} connected.".format(self.__socket.getpeername()))
        while True:
            logging.debug("handle({}) loop.".format(self.__socket.getpeername()))
            # receive 2 bytes size header
            size = self.__recv(2)
            if not size:
                logging.debug("Did not receive 2 bytes header.")
                break
            size = struct.unpack('>H', size)[0]
            logging.debug("Size: " + str(size))

            # receive message body
            msg = self.__recv(size)
            if not msg:
                logging.debug("Did not receive {} bytes body.".format(str(size)))
                break

            # explode received data into message type and parameters
            msgtype, msgparams = self.__message_parser.decode(msg.decode())
            logging.debug("Msg type: " + msgtype)
            logging.debug("Msg parameters: " + repr(msgparams))

            # dispatch message type
            if msgtype == messages.CREATE_GAME:
                self.__create_game(msgparams)
            elif msgtype == messages.JOIN_GAME:
                self.__join_game(msgparams)
            elif msgtype == messages.SET_NICK:
                self.__set_nickname(msgparams)
            elif msgtype == messages.LEAVE_GAME:
                self.__leave_game()
            elif msgtype == messages.INIT_BOARD:
                self.__init_board(msgparams)
            elif msgtype == messages.FIRE:
                self.__fire(msgparams)
            elif msgtype == messages.NUKE:
                self.__nuke(msgparams)
            elif msgtype == messages.MOVE:
                self.__move(msgparams)
            elif msgtype == messages.SURRENDER:
                self.__surrender()
            elif msgtype == messages.CHAT_SEND:
                self.__chat(msgparams)
            else:
                self.__unknown_msg()

    #
    # Callbacks
    #

    def on_update_lobby(self):
        logging.debug("on_update_lobby()")

        # Get required data for update lobby msg
        number_of_clients = self.__lobby_model.get_number_of_players()
        number_of_games = self.__lobby_model.get_number_of_games()
        games_info = self.__lobby_model.get_games_info()
        players_info = self.__lobby_model.get_players_info()

        # Update_Lobby
        data = {
            'status': 16,
            'number_of_clients': number_of_clients,
            'number_of_games': number_of_games[0]
        }

        i = 0
        weirdkey = 'game_name_{}'
        moreweirdkeys = 'game_players_count_{}'
        whatevenisthis = 'game_player_{}_{}'
        waitwhat = 'player_name_{}'
        yetanotherkey = 'player_identifier_{}'

        for game in games_info:
            # game stuff
            data[weirdkey.format(i)] = game['game_name']
            data[moreweirdkeys.format(i)] = game['number_of_players']
            # player 1 stuff
            data[whatevenisthis.format(i, 0)] = game['ids'][0]
            # player 2 stuff
            if game['number_of_players'] == 2:
                data[whatevenisthis.format(i, 1)] = game['ids'][1]
            i += 1

        i = 0
        for player in players_info:
            # player stuff
            data[yetanotherkey.format(i)] = player['id']
            data[waitwhat.format(i)] = player['nickname']
            i += 1

        msg = self.__message_parser.encode('report', data)
        self.__send(msg)

    def on_game_abort(self):
        # delete game
        self.__lobby_model.delete_game(self.__game)
        self.__game = None

        self.__send(self.__message_parser.encode('report', {'status': '19'}))

    def on_game_ended(self, winner, id0, id1, timestamp):
        msg = {
            'status': '17',
            'winner': winner - 1,
            'name_of_game': self.__game,
            'timestamp': timestamp,
            'identifier_0': id0,
            'identifier_1': id1,
            'reason_for_game_end': 'Because of reasons.'
        }

        # delete game
        self.__lobby_model.delete_game(self.__game)
        self.__game = None

        self.__send(self.__message_parser.encode('report', msg))

    def on_ship_edit(self):
        logging.debug('on_ship_edit()')
        self.__send(self.__message_parser.encode('report', {'status': '18'}))

    def on_game_start(self):
        logging.debug('on_game_start()')
        self.__send(self.__message_parser.encode('report', {'status': '48'}))

    def on_host_begins(self):
        logging.debug('on_host_begins()')
        self.__begin_turn()

    def on_guest_begins(self):
        logging.debug('on_guest_begins()')
        self.__begin_turn()

    def on_attack(self, x, y, condition):
        logging.debug('on_attack()')
        msg = None
        # if player is enemy
        if self.__lobby_model.get_game(self.__game).get_turn() == self.__player:
            # update own field
            msg = {
                'status': 13,
                'was_special_attack': 'false',
                'coordinate_x': x,
                'coordinate_y': y
            }
            self.__send(self.__message_parser.encode('report', msg))
            # trigger next turn wtf
            self.__begin_turn()
        else:
            # update enemy field
            msg = {
                'status': 14,
                'number_of_updated_fields': '1',
                'field_0_x': x,
                'field_0_y': y,
                'field_0_condition': condition
            }
            self.__send(self.__message_parser.encode('report', msg))

    def on_special_attack(self, x, y, updates):
        logging.debug('on_special_attack()')
        msg = None
        if self.__lobby_model.get_game(self.__game).get_turn() == self.__player:
            # update own field
            msg = {
                'status': 13,
                'was_special_attack': 'true',
                'coordinate_x': x,
                'coordinate_y': y
            }
            self.__send(self.__message_parser.encode('report', msg))
            # trigger next turn wtf
            self.__begin_turn()
        else:
            # update enemy field
            msg = {
                'status': 14,
                'number_of_updated_fields': len(updates)
            }
            i = 0
            for j in updates:
                msg['field_{}_x'.format(i)] = j['field'].x
                msg['field_{}_y'.format(i)] =j['field'].y
                msg['field_{}_condition'.format(i)] = j['status']
                i += 1
            self.__send(self.__message_parser.encode('report', msg))

    def on_move(self, updates):
        logging.debug('on_move()')
        msg = None
        if self.__lobby_model.get_game(self.__game).get_turn() == self.__player:
            # update enemy field
            if len(updates) > 0:
                msg = {
                    'status': 14,
                    'number_of_updated_fields': len(updates)
                }
                i = 0
                for j in updates:
                    msg['field_{}_x'.format(i)] = j['field'].x
                    msg['field_{}_y'.format(i)] =j['field'].y
                    msg['field_{}_condition'.format(i)] = j['status']
                    i += 1
                self.__send(self.__message_parser.encode('report', msg))
            # trigger next turn wtf
            self.__begin_turn()

    def on_chat(self, timestamp, player, msg):
        logging.debug('on_chat()')
        msg = {
            'status': '15',
            'author_id': player,
            'timestamp': timestamp,
            'message_content': msg
        }
        self.__send(self.__message_parser.encode('report', msg))

    def get_socket(self):
        return self.__socket

    def finish(self):
        logging.info("Client disconnected.")

        # remove any left callbacks
        self.__lobby_model.remove_callback(LobbyEvent.on_update, self.on_update_lobby)
        self.__lobby_model.remove_callback(LobbyEvent.on_chat, self.on_chat)

        # end running game if any
        if self.__game and self.__lobby_model.get_game(self.__game) is not None:
            # remove callbacks of disconnected player
            self.__lobby_model.get_game(self.__game).remove_callback(GameEvent.on_ship_edit, self.on_ship_edit)
            self.__lobby_model.get_game(self.__game).remove_callback(GameEvent.on_game_start, self.on_game_start)
            self.__lobby_model.get_game(self.__game).remove_callback(GameEvent.on_attack, self.on_attack)
            self.__lobby_model.get_game(self.__game).remove_callback(GameEvent.on_special_attack, self.on_special_attack)
            self.__lobby_model.get_game(self.__game).remove_callback(GameEvent.on_move, self.on_move)
            #self.__lobby_model.get_game(self.__game).remove_callback(GameEvent.on_host_begins, self.on_host_begins)
            #self.__lobby_model.get_game(self.__game).remove_callback(GameEvent.on_guest_begins, self.on_guest_begins)
            self.__lobby_model.get_game(self.__game).remove_callback(GameEvent.on_game_ended, self.on_game_ended)
            self.__lobby_model.get_game(self.__game).remove_callback(GameEvent.on_game_abort, self.on_game_abort)

            # surrender
            if self.__lobby_model.get_game(self.__game).is_ongoing():
                logging.debug("Surrender by disconnect.")
                self.__lobby_model.get_game(self.__game).surrender(self.__player)
            # abort
            elif self.__lobby_model.get_game(self.__game).is_ready():
                logging.debug("Abort by disconnect.")
                self.__lobby_model.get_game(self.__game).abort()

        # remove player from lobby
        self.__lobby_model.delete_player(self.__id)

    def __create_game(self, params):
        # make sure parameter list is complete
        if not self.__expect_parameter(['name'], params):
            return

        # check if client is already in a game
        if self.__game:
            logging.debug("Client already in some game.")
            # 31 is the new 42
            self.__send(self.__message_parser.encode('report', {'status': '31'}))
            return

        # check game name length
        if 1 > len(params['name']) or len(params['name']) > 64:
            logging.debug("Game name too long.")
            self.__send(self.__message_parser.encode('report', {'status': '37'}))
            return

        # create the game
        game = self.__lobby_model.add_lobby(params['name'], self.__id)

        if not game:
            self.__send(self.__message_parser.encode('report', {'status': '37'}))
            return

        self.__game = params['name']
        self.__player = 1
        self.__send(self.__message_parser.encode('report', {'status': '28'}))

        # register game callbacks
        self.__lobby_model.get_game(self.__game).register_callback(GameEvent.on_ship_edit, self.on_ship_edit)
        self.__lobby_model.get_game(self.__game).register_callback(GameEvent.on_game_start, self.on_game_start)
        self.__lobby_model.get_game(self.__game).register_callback(GameEvent.on_attack, self.on_attack)
        self.__lobby_model.get_game(self.__game).register_callback(GameEvent.on_special_attack, self.on_special_attack)
        self.__lobby_model.get_game(self.__game).register_callback(GameEvent.on_move, self.on_move)
        self.__lobby_model.get_game(self.__game).register_callback(GameEvent.on_host_begins, self.on_host_begins)
        self.__lobby_model.get_game(self.__game).register_callback(GameEvent.on_game_ended, self.on_game_ended)
        self.__lobby_model.get_game(self.__game).register_callback(GameEvent.on_game_abort, self.on_game_abort)

    def __join_game(self, params):
        # make sure parameter list is complete
        if not self.__expect_parameter(['name'], params):
            return

        # check if client is already in a game
        if self.__game:
            logging.debug("Client already in some game.")
            self.__send(self.__message_parser.encode('report', {'status': '31'}))
            return

        # join the game
        game, e = self.__lobby_model.join_lobby(params['name'], self.__id)

        # handle game join errors
        if e:
            if e == LobbyError.game_is_full:
                self.__send(self.__message_parser.encode('report', {'status': '47'}))
                return
            elif e == LobbyError.game_does_not_exist:
                self.__send(self.__message_parser.encode('report', {'status': '37'}))
                return

        # ack game join
        self.__send(self.__message_parser.encode('report', {'status': '27'}))

        self.__game = params['name']
        self.__player = 2

        # register game callbacks
        self.__lobby_model.get_game(self.__game).register_callback(GameEvent.on_ship_edit, self.on_ship_edit)
        self.__lobby_model.get_game(self.__game).register_callback(GameEvent.on_game_start, self.on_game_start)
        self.__lobby_model.get_game(self.__game).register_callback(GameEvent.on_attack, self.on_attack)
        self.__lobby_model.get_game(self.__game).register_callback(GameEvent.on_special_attack, self.on_special_attack)
        self.__lobby_model.get_game(self.__game).register_callback(GameEvent.on_move, self.on_move)
        self.__lobby_model.get_game(self.__game).register_callback(GameEvent.on_guest_begins, self.on_guest_begins)
        self.__lobby_model.get_game(self.__game).register_callback(GameEvent.on_game_ended, self.on_game_ended)
        self.__lobby_model.get_game(self.__game).register_callback(GameEvent.on_game_abort, self.on_game_abort)

        self.__lobby_model.get_game(self.__game).just_begin_ship_placement_already()

    def __set_nickname(self, params):
        if not self.__expect_parameter(['name'], params):
            return

        if len(params['name']) > 64:
            logging.debug("Nickname too long.")
            self.__send(self.__message_parser.encode('report', {'status': '36'}))
            return

        # tell lobby to set nickname and hope for the best
        self.__lobby_model.set_nickname(self.__id, params['name'])

    def __get_own_player_id(self):
        addr, port = self.__socket.getpeername()
        playerid = hashlib.sha1(b(addr + str(port))).hexdigest()
        return playerid

    def __init_board(self, params):
        logging.debug('__init_board()')

        # not in any game
        if self.__game is None:
            self.__send(self.__message_parser.encode('report', {'status': '43'}))
            return

        shipx = 'ship_{}_x'
        shipy = 'ship_{}_y'
        shipdir = 'ship_{}_direction'

        # make sure that all parameters exist
        if not self.__expect_parameter(
            [shipx.format(i) for i in range(0, 10)] +
            [shipy.format(i) for i in range(0, 10)] +
            [shipdir.format(i) for i in range(0, 10)], params):
            return

        # init board
        left = True
        for id in range(0, 10):
            x = int(params[shipx.format(id)])
            y = int(params[shipy.format(id)])
            dir = params[shipdir.format(id)]
            logging.debug('self.__lobby_model :: {}'.format(repr(self.__lobby_model)))
            logging.debug('self.__lobby_model.get_game(self.__game) :: {}'.format(repr(self.__lobby_model.get_game(self.__game))))
            logging.debug('self.__game :: {}'.format(repr(self.__game)))
            suc, left = self.__lobby_model.get_game(self.__game).place_ship(self.__player, x, y, dir, id)

            # catch illegal placement
            if suc == -1:
                logging.debug("Nonsense ship placement.")
                self.__send(self.__message_parser.encode('report', {'status': '38'}))
                return

        if left:
            logging.debug("Something is still wrong with ship placement.")
            self.__send(self.__message_parser.encode('report', {'status': '38'}))
            return

        # ack init board
        self.__send(self.__message_parser.encode('report', {'status': '29'}))

        # trigger random begin return message
        self.__lobby_model.get_game(self.__game).start()

    def __leave_game(self):
        # not in any game
        if self.__game is None:
            self.__send(self.__message_parser.encode('report', {'status': '43'}))
            return

        # make sure the game has not started yet
        if self.__lobby_model.get_game(self.__game).is_ongoing():
            self.__send(self.__message_parser.encode('report', {'status': '43'}))
            logging.debug("Too late to leave the game.")
            return

        # abort
        self.__lobby_model.get_game(self.__game).abort()

    def __fire(self, params):
        if not self.__expect_parameter(['coordinate_x', 'coordinate_y'], params):
            return

        # not in any game
        if self.__game is None:
            self.__send(self.__message_parser.encode('report', {'status': '43'}))
            return

        # check if it's actually your turn
        if self.__lobby_model.get_game(self.__game).get_turn() != self.__player:
            self.__send(self.__message_parser.encode('report', {'status': '41'}))
            return

        # check if coordinates are valid
        if not ((0 <= int(params['coordinate_x']) <= 15) and (0 <= int(params['coordinate_y']) <= 15)):
            self.__send(self.__message_parser.encode('report', {'status': '39'}))
            return

        # save move
        _, updated = self.__lobby_model.get_game(self.__game).fire(self.__player, params['coordinate_x'], params['coordinate_y'])
        logging.debug("Fire: updated is {}.".format(updated))
        #if not updated:
        #    self.__send(self.__message_parser.encode('report', {'status': '39'}))
        #    return

        # successful attack
        self.__send(self.__message_parser.encode('report', {'status': '22'}))

        # check if game over
        self.__lobby_model.get_game(self.__game).check_if_game_over(self.__player)

    def __nuke(self, params):
        if not self.__expect_parameter(['coordinate_x', 'coordinate_y'], params):
            return

        # check if coordinates are valid
        if not ((0 <= int(params['coordinate_x']) <= 13) and (0 <= int(params['coordinate_y']) <= 13)):
            self.__send(self.__message_parser.encode('report', {'status': '32'}))
            return

        # not in any game
        if self.__game is None:
            self.__send(self.__message_parser.encode('report', {'status': '43'}))
            return

        # check if it's actually your turn
        if self.__lobby_model.get_game(self.__game).get_turn() != self.__player:
            self.__send(self.__message_parser.encode('report', {'status': '41'}))
            return

        # save move
        updated = self.__lobby_model.get_game(self.__game).nuke(self.__player, params['coordinate_x'], params['coordinate_y'])

        # special attack failed
        if updated is False:
            self.__send(self.__message_parser.encode('report', {'status': '32'}))
            return

        logging.debug("Nuke: updated {} fields.".format(len(updated)))
        #if len(updated) == 0:
        #    self.__send(self.__message_parser.encode('report', {'status': '32'}))
        #    return

        # successful special attack
        self.__send(self.__message_parser.encode('report', {'status': '24'}))

        # check if game over
        self.__lobby_model.get_game(self.__game).check_if_game_over(self.__player)

    def __move(self, params):
        if not self.__expect_parameter(['ship_id', 'direction'], params):
            return

        # not in any game
        if self.__game is None:
            self.__send(self.__message_parser.encode('report', {'status': '43'}))
            return

        # check if it's actually your turn
        if self.__lobby_model.get_game(self.__game).get_turn() != self.__player:
            self.__send(self.__message_parser.encode('report', {'status': '41'}))
            return

        # save move
        result = self.__lobby_model.get_game(self.__game).move_ship(self.__player, int(params['ship_id']), params['direction'])
        if result is False:
            self.__send(self.__message_parser.encode('report', {'status': '31'}))
            return

        # successful move
        self.__send(self.__message_parser.encode('report', {'status': '21'}))

    def __surrender(self):
        # not in any game
        if self.__game is None:
            self.__send(self.__message_parser.encode('report', {'status': '43'}))
            return

        # make sure the game is ongoing
        if not self.__lobby_model.get_game(self.__game).is_ongoing():
            self.__send(self.__message_parser.encode('report', {'status': '43'}))
            return

        # surrender
        self.__lobby_model.get_game(self.__game).surrender(self.__player)

        # surrender accepted lol
        self.__send(self.__message_parser.encode('report', {'status': '23'}))

    def __begin_turn(self):
        self.__send(self.__message_parser.encode('report', {'status': '11'}))

    def __chat(self, params):
        if not self.__expect_parameter(['text'], params):
            return
        self.__lobby_model.chat(self.__id, params['text'])

    def __unknown_msg(self):
        self.__send(self.__message_parser.encode('report', {'status': '40'}))

    def __expect_parameter(self, expected, actual):
        keys = list(actual.keys())
        for p in expected:
            if p not in keys:
                self.__unknown_msg()
                return False
        return True

    def __recv(self, count):
        try:
            msg = self.__socket.recv(count)
        except socket.error as e:
            logging.debug("Client already dead: ".format(repr(e)))
            return
        logging.debug(b"Raw in: " + msg)
        return msg

    def __send(self, msg):
        try:
            self.__socket.sendall(msg)
        except socket.error as e:
            logging.debug("Client already dead: ".format(repr(e)))
            return
        logging.debug(b"Raw out: " + msg)
class RoverSim():
    def __init__(self, roverID, blockInfo):
        self.roverID = roverID
        self.blockInfo = blockInfo
        self.posY = 0
        self.nextY = 0
        if roverID == 0:
            self.posX = 0
            self.nextX = 0
        else:
            self.posX = -1
            self.nextX = -1

        # Declare test client and parser
        self.clientConnection = TestClient()
        self.parser = MessageParser(roverID)

        # Connect signals and slots
        self.clientConnection.messageFromServer.connect(self.parser.parse)
        self.parser.parsedMessageSignal.connect(self.messageFromServer)
        self.parser.constructedMessageSignal.connect(
            self.clientConnection.sendMessageToServer)

    def ack(self, command):
        self.parser.constructMessage(commandDefs.flags["COMMAND_RECEIVED"] +
                                     ' ' + command)

    def finish(self, command):
        time.sleep(0.5)  # Pause for command to complete
        self.parser.constructMessage(commandDefs.flags["COMMAND_FINISHED"] +
                                     ' ' + command)

    def eventAlert(self):
        self.parser.constructMessage(commandDefs.flags["EVENT_ALERT"])

    # Handler for server commands
    def messageFromServer(self, message):
        # Acknowledge message
        self.ack(message)

        messageFields = message.split(' ')
        # Compute new position if necessary
        if messageFields[0] == commandDefs.commands[
                "MOVE_COMMAND"] or messageFields[0] == commandDefs.commands[
                    "PICKUP_COMMAND"]:
            if messageFields[1] == commandDefs.specifiers["NORTH_MOVE"]:
                self.nextX = self.posX
                self.nextY = self.posY + 1
                self.executeMove(message)
            elif messageFields[1] == commandDefs.specifiers["EAST_MOVE"]:
                self.nextX = self.posX + 1
                self.nextY = self.posY
                self.executeMove(message)
            elif messageFields[1] == commandDefs.specifiers["SOUTH_MOVE"]:
                self.nextX = self.posX
                self.nextY = self.posY - 1
                self.executeMove(message)
            elif messageFields[1] == commandDefs.specifiers["WEST_MOVE"]:
                self.nextX = self.posX - 1
                self.nextY = self.posY
                self.executeMove(message)
        # Send reading for a read command
        elif messageFields[0] == commandDefs.commands["READ_COMMAND"]:
            self.parser.constructMessage(
                commandDefs.flags["EVENT_ALERT"] + ' ' +
                self.blockInfo[8 - self.nextY][self.nextX])
            self.finish(message)
        # Finish any other command
        else:
            self.finish(message)

    def blockAtPos(self, x, y):
        if self.blockInfo[8 - y][x] != 'N':
            return self.blockInfo[8 - y][x]
        else:
            return None

    def updatePos(self):
        self.posX = self.nextX
        self.posY = self.nextY
        print("New positiion: ", self.posX, ', ', self.posY)

    def executeMove(self, message):
        if self.roverID == 0:
            if not self.blockAtPos(self.nextX,
                                   self.nextY):  # if no block is in the way
                self.updatePos()  # update position and finish command
                self.finish(message)
            else:  # if a block is in the way
                self.eventAlert()  # send an event alert
        else:
            self.updatePos()  # Moves always succeed for rover1
            self.finish(message)

    def run(self):
        app = QApplication(sys.argv)
        self.clientConnection.begin.emit()
        sys.exit(app.exec())
Example #13
0
import socket
from channel import Channel
from messageparser import MessageParser

mp = MessageParser()


def serv_log(text):
    print("[Server] {}".format(text))


def irc_log(t, text):
    print("[{0}] {1}".format(t, text))


###################
# Server responses#
###################


def confirm_reg(conn, data, host):
    msg = ":{0} 001 {1} :Hi welcome to this IRC server \r\n".format(
        host, data.nick)
    conn.send(msg.encode())
    irc_log("OUT", msg.strip())

    msg = ":{0} 002 {1} :Your host is {0} IRC server made as an assignment \r\n".format(
        host, data.nick)
    conn.send(msg.encode())
    irc_log("OUT", msg.strip())
Example #14
0
class ClientHandler:
    def __init__(self, sock):
        self.__socket = sock
        self.__message_parser = MessageParser()
        self.__lobby_model = LobbyModel()
        # name of the game
        self.__game = None
        # player number (1 or 2)
        self.__player = None
        # player id lol
        self.__id = self.__get_own_player_id()
        # add client as player
        self.__lobby_model.add_player(self.__id)

        # register callbacks
        self.__lobby_model.register_callback(LobbyEvent.on_update,
                                             self.on_update_lobby)
        self.__lobby_model.register_callback(LobbyEvent.on_chat, self.on_chat)

    def handle(self):
        logging.info("Client {} connected.".format(
            self.__socket.getpeername()))
        while True:
            logging.debug("handle({}) loop.".format(
                self.__socket.getpeername()))
            # receive 2 bytes size header
            size = self.__recv(2)
            if not size:
                logging.debug("Did not receive 2 bytes header.")
                break
            size = struct.unpack('>H', size)[0]
            logging.debug("Size: " + str(size))

            # receive message body
            msg = self.__recv(size)
            if not msg:
                logging.debug("Did not receive {} bytes body.".format(
                    str(size)))
                break

            # explode received data into message type and parameters
            msgtype, msgparams = self.__message_parser.decode(msg.decode())
            logging.debug("Msg type: " + msgtype)
            logging.debug("Msg parameters: " + repr(msgparams))

            # dispatch message type
            if msgtype == messages.CREATE_GAME:
                self.__create_game(msgparams)
            elif msgtype == messages.JOIN_GAME:
                self.__join_game(msgparams)
            elif msgtype == messages.SET_NICK:
                self.__set_nickname(msgparams)
            elif msgtype == messages.LEAVE_GAME:
                self.__leave_game()
            elif msgtype == messages.INIT_BOARD:
                self.__init_board(msgparams)
            elif msgtype == messages.FIRE:
                self.__fire(msgparams)
            elif msgtype == messages.NUKE:
                self.__nuke(msgparams)
            elif msgtype == messages.MOVE:
                self.__move(msgparams)
            elif msgtype == messages.SURRENDER:
                self.__surrender()
            elif msgtype == messages.CHAT_SEND:
                self.__chat(msgparams)
            else:
                self.__unknown_msg()

    #
    # Callbacks
    #

    def on_update_lobby(self):
        logging.debug("on_update_lobby()")

        # Get required data for update lobby msg
        number_of_clients = self.__lobby_model.get_number_of_players()
        number_of_games = self.__lobby_model.get_number_of_games()
        games_info = self.__lobby_model.get_games_info()
        players_info = self.__lobby_model.get_players_info()

        # Update_Lobby
        data = {
            'status': 16,
            'number_of_clients': number_of_clients,
            'number_of_games': number_of_games[0]
        }

        i = 0
        weirdkey = 'game_name_{}'
        moreweirdkeys = 'game_players_count_{}'
        whatevenisthis = 'game_player_{}_{}'
        waitwhat = 'player_name_{}'
        yetanotherkey = 'player_identifier_{}'

        for game in games_info:
            # game stuff
            data[weirdkey.format(i)] = game['game_name']
            data[moreweirdkeys.format(i)] = game['number_of_players']
            # player 1 stuff
            data[whatevenisthis.format(i, 0)] = game['ids'][0]
            # player 2 stuff
            if game['number_of_players'] == 2:
                data[whatevenisthis.format(i, 1)] = game['ids'][1]
            i += 1

        i = 0
        for player in players_info:
            # player stuff
            data[yetanotherkey.format(i)] = player['id']
            data[waitwhat.format(i)] = player['nickname']
            i += 1

        msg = self.__message_parser.encode('report', data)
        self.__send(msg)

    def on_game_abort(self):
        # delete game
        self.__lobby_model.delete_game(self.__game)
        self.__game = None

        self.__send(self.__message_parser.encode('report', {'status': '19'}))

    def on_game_ended(self, winner, id0, id1, timestamp):
        msg = {
            'status': '17',
            'winner': winner - 1,
            'name_of_game': self.__game,
            'timestamp': timestamp,
            'identifier_0': id0,
            'identifier_1': id1,
            'reason_for_game_end': 'Because of reasons.'
        }

        # delete game
        self.__lobby_model.delete_game(self.__game)
        self.__game = None

        self.__send(self.__message_parser.encode('report', msg))

    def on_ship_edit(self):
        logging.debug('on_ship_edit()')
        self.__send(self.__message_parser.encode('report', {'status': '18'}))

    def on_game_start(self):
        logging.debug('on_game_start()')
        self.__send(self.__message_parser.encode('report', {'status': '48'}))

    def on_host_begins(self):
        logging.debug('on_host_begins()')
        self.__begin_turn()

    def on_guest_begins(self):
        logging.debug('on_guest_begins()')
        self.__begin_turn()

    def on_attack(self, x, y, condition):
        logging.debug('on_attack()')
        msg = None
        # if player is enemy
        if self.__lobby_model.get_game(
                self.__game).get_turn() == self.__player:
            # update own field
            msg = {
                'status': 13,
                'was_special_attack': 'false',
                'coordinate_x': x,
                'coordinate_y': y
            }
            self.__send(self.__message_parser.encode('report', msg))
            # trigger next turn wtf
            self.__begin_turn()
        else:
            # update enemy field
            msg = {
                'status': 14,
                'number_of_updated_fields': '1',
                'field_0_x': x,
                'field_0_y': y,
                'field_0_condition': condition
            }
            self.__send(self.__message_parser.encode('report', msg))

    def on_special_attack(self, x, y, updates):
        logging.debug('on_special_attack()')
        msg = None
        if self.__lobby_model.get_game(
                self.__game).get_turn() == self.__player:
            # update own field
            msg = {
                'status': 13,
                'was_special_attack': 'true',
                'coordinate_x': x,
                'coordinate_y': y
            }
            self.__send(self.__message_parser.encode('report', msg))
            # trigger next turn wtf
            self.__begin_turn()
        else:
            # update enemy field
            msg = {'status': 14, 'number_of_updated_fields': len(updates)}
            i = 0
            for j in updates:
                msg['field_{}_x'.format(i)] = j['field'].x
                msg['field_{}_y'.format(i)] = j['field'].y
                msg['field_{}_condition'.format(i)] = j['status']
                i += 1
            self.__send(self.__message_parser.encode('report', msg))

    def on_move(self, updates):
        logging.debug('on_move()')
        msg = None
        if self.__lobby_model.get_game(
                self.__game).get_turn() == self.__player:
            # update enemy field
            if len(updates) > 0:
                msg = {'status': 14, 'number_of_updated_fields': len(updates)}
                i = 0
                for j in updates:
                    msg['field_{}_x'.format(i)] = j['field'].x
                    msg['field_{}_y'.format(i)] = j['field'].y
                    msg['field_{}_condition'.format(i)] = j['status']
                    i += 1
                self.__send(self.__message_parser.encode('report', msg))
            # trigger next turn wtf
            self.__begin_turn()

    def on_chat(self, timestamp, player, msg):
        logging.debug('on_chat()')
        msg = {
            'status': '15',
            'author_id': player,
            'timestamp': timestamp,
            'message_content': msg
        }
        self.__send(self.__message_parser.encode('report', msg))

    def get_socket(self):
        return self.__socket

    def finish(self):
        logging.info("Client disconnected.")

        # remove any left callbacks
        self.__lobby_model.remove_callback(LobbyEvent.on_update,
                                           self.on_update_lobby)
        self.__lobby_model.remove_callback(LobbyEvent.on_chat, self.on_chat)

        # end running game if any
        if self.__game and self.__lobby_model.get_game(
                self.__game) is not None:
            # remove callbacks of disconnected player
            self.__lobby_model.get_game(self.__game).remove_callback(
                GameEvent.on_ship_edit, self.on_ship_edit)
            self.__lobby_model.get_game(self.__game).remove_callback(
                GameEvent.on_game_start, self.on_game_start)
            self.__lobby_model.get_game(self.__game).remove_callback(
                GameEvent.on_attack, self.on_attack)
            self.__lobby_model.get_game(self.__game).remove_callback(
                GameEvent.on_special_attack, self.on_special_attack)
            self.__lobby_model.get_game(self.__game).remove_callback(
                GameEvent.on_move, self.on_move)
            #self.__lobby_model.get_game(self.__game).remove_callback(GameEvent.on_host_begins, self.on_host_begins)
            #self.__lobby_model.get_game(self.__game).remove_callback(GameEvent.on_guest_begins, self.on_guest_begins)
            self.__lobby_model.get_game(self.__game).remove_callback(
                GameEvent.on_game_ended, self.on_game_ended)
            self.__lobby_model.get_game(self.__game).remove_callback(
                GameEvent.on_game_abort, self.on_game_abort)

            # surrender
            if self.__lobby_model.get_game(self.__game).is_ongoing():
                logging.debug("Surrender by disconnect.")
                self.__lobby_model.get_game(self.__game).surrender(
                    self.__player)
            # abort
            elif self.__lobby_model.get_game(self.__game).is_ready():
                logging.debug("Abort by disconnect.")
                self.__lobby_model.get_game(self.__game).abort()

        # remove player from lobby
        self.__lobby_model.delete_player(self.__id)

    def __create_game(self, params):
        # make sure parameter list is complete
        if not self.__expect_parameter(['name'], params):
            return

        # check if client is already in a game
        if self.__game:
            logging.debug("Client already in some game.")
            # 31 is the new 42
            self.__send(
                self.__message_parser.encode('report', {'status': '31'}))
            return

        # check game name length
        if 1 > len(params['name']) or len(params['name']) > 64:
            logging.debug("Game name too long.")
            self.__send(
                self.__message_parser.encode('report', {'status': '37'}))
            return

        # create the game
        game = self.__lobby_model.add_lobby(params['name'], self.__id)

        if not game:
            self.__send(
                self.__message_parser.encode('report', {'status': '37'}))
            return

        self.__game = params['name']
        self.__player = 1
        self.__send(self.__message_parser.encode('report', {'status': '28'}))

        # register game callbacks
        self.__lobby_model.get_game(self.__game).register_callback(
            GameEvent.on_ship_edit, self.on_ship_edit)
        self.__lobby_model.get_game(self.__game).register_callback(
            GameEvent.on_game_start, self.on_game_start)
        self.__lobby_model.get_game(self.__game).register_callback(
            GameEvent.on_attack, self.on_attack)
        self.__lobby_model.get_game(self.__game).register_callback(
            GameEvent.on_special_attack, self.on_special_attack)
        self.__lobby_model.get_game(self.__game).register_callback(
            GameEvent.on_move, self.on_move)
        self.__lobby_model.get_game(self.__game).register_callback(
            GameEvent.on_host_begins, self.on_host_begins)
        self.__lobby_model.get_game(self.__game).register_callback(
            GameEvent.on_game_ended, self.on_game_ended)
        self.__lobby_model.get_game(self.__game).register_callback(
            GameEvent.on_game_abort, self.on_game_abort)

    def __join_game(self, params):
        # make sure parameter list is complete
        if not self.__expect_parameter(['name'], params):
            return

        # check if client is already in a game
        if self.__game:
            logging.debug("Client already in some game.")
            self.__send(
                self.__message_parser.encode('report', {'status': '31'}))
            return

        # join the game
        game, e = self.__lobby_model.join_lobby(params['name'], self.__id)

        # handle game join errors
        if e:
            if e == LobbyError.game_is_full:
                self.__send(
                    self.__message_parser.encode('report', {'status': '47'}))
                return
            elif e == LobbyError.game_does_not_exist:
                self.__send(
                    self.__message_parser.encode('report', {'status': '37'}))
                return

        # ack game join
        self.__send(self.__message_parser.encode('report', {'status': '27'}))

        self.__game = params['name']
        self.__player = 2

        # register game callbacks
        self.__lobby_model.get_game(self.__game).register_callback(
            GameEvent.on_ship_edit, self.on_ship_edit)
        self.__lobby_model.get_game(self.__game).register_callback(
            GameEvent.on_game_start, self.on_game_start)
        self.__lobby_model.get_game(self.__game).register_callback(
            GameEvent.on_attack, self.on_attack)
        self.__lobby_model.get_game(self.__game).register_callback(
            GameEvent.on_special_attack, self.on_special_attack)
        self.__lobby_model.get_game(self.__game).register_callback(
            GameEvent.on_move, self.on_move)
        self.__lobby_model.get_game(self.__game).register_callback(
            GameEvent.on_guest_begins, self.on_guest_begins)
        self.__lobby_model.get_game(self.__game).register_callback(
            GameEvent.on_game_ended, self.on_game_ended)
        self.__lobby_model.get_game(self.__game).register_callback(
            GameEvent.on_game_abort, self.on_game_abort)

        self.__lobby_model.get_game(
            self.__game).just_begin_ship_placement_already()

    def __set_nickname(self, params):
        if not self.__expect_parameter(['name'], params):
            return

        if len(params['name']) > 64:
            logging.debug("Nickname too long.")
            self.__send(
                self.__message_parser.encode('report', {'status': '36'}))
            return

        # tell lobby to set nickname and hope for the best
        self.__lobby_model.set_nickname(self.__id, params['name'])

    def __get_own_player_id(self):
        addr, port = self.__socket.getpeername()
        playerid = hashlib.sha1(b(addr + str(port))).hexdigest()
        return playerid

    def __init_board(self, params):
        logging.debug('__init_board()')

        # not in any game
        if self.__game is None:
            self.__send(
                self.__message_parser.encode('report', {'status': '43'}))
            return

        shipx = 'ship_{}_x'
        shipy = 'ship_{}_y'
        shipdir = 'ship_{}_direction'

        # make sure that all parameters exist
        if not self.__expect_parameter(
            [shipx.format(i)
             for i in range(0, 10)] + [shipy.format(i) for i in range(0, 10)] +
            [shipdir.format(i) for i in range(0, 10)], params):
            return

        # init board
        left = True
        for id in range(0, 10):
            x = int(params[shipx.format(id)])
            y = int(params[shipy.format(id)])
            dir = params[shipdir.format(id)]
            logging.debug('self.__lobby_model :: {}'.format(
                repr(self.__lobby_model)))
            logging.debug(
                'self.__lobby_model.get_game(self.__game) :: {}'.format(
                    repr(self.__lobby_model.get_game(self.__game))))
            logging.debug('self.__game :: {}'.format(repr(self.__game)))
            suc, left = self.__lobby_model.get_game(self.__game).place_ship(
                self.__player, x, y, dir, id)

            # catch illegal placement
            if suc == -1:
                logging.debug("Nonsense ship placement.")
                self.__send(
                    self.__message_parser.encode('report', {'status': '38'}))
                return

        if left:
            logging.debug("Something is still wrong with ship placement.")
            self.__send(
                self.__message_parser.encode('report', {'status': '38'}))
            return

        # ack init board
        self.__send(self.__message_parser.encode('report', {'status': '29'}))

        # trigger random begin return message
        self.__lobby_model.get_game(self.__game).start()

    def __leave_game(self):
        # not in any game
        if self.__game is None:
            self.__send(
                self.__message_parser.encode('report', {'status': '43'}))
            return

        # make sure the game has not started yet
        if self.__lobby_model.get_game(self.__game).is_ongoing():
            self.__send(
                self.__message_parser.encode('report', {'status': '43'}))
            logging.debug("Too late to leave the game.")
            return

        # abort
        self.__lobby_model.get_game(self.__game).abort()

    def __fire(self, params):
        if not self.__expect_parameter(['coordinate_x', 'coordinate_y'],
                                       params):
            return

        # not in any game
        if self.__game is None:
            self.__send(
                self.__message_parser.encode('report', {'status': '43'}))
            return

        # check if it's actually your turn
        if self.__lobby_model.get_game(
                self.__game).get_turn() != self.__player:
            self.__send(
                self.__message_parser.encode('report', {'status': '41'}))
            return

        # check if coordinates are valid
        if not ((0 <= int(params['coordinate_x']) <= 15) and
                (0 <= int(params['coordinate_y']) <= 15)):
            self.__send(
                self.__message_parser.encode('report', {'status': '39'}))
            return

        # save move
        _, updated = self.__lobby_model.get_game(self.__game).fire(
            self.__player, params['coordinate_x'], params['coordinate_y'])
        logging.debug("Fire: updated is {}.".format(updated))
        #if not updated:
        #    self.__send(self.__message_parser.encode('report', {'status': '39'}))
        #    return

        # successful attack
        self.__send(self.__message_parser.encode('report', {'status': '22'}))

        # check if game over
        self.__lobby_model.get_game(self.__game).check_if_game_over(
            self.__player)

    def __nuke(self, params):
        if not self.__expect_parameter(['coordinate_x', 'coordinate_y'],
                                       params):
            return

        # check if coordinates are valid
        if not ((0 <= int(params['coordinate_x']) <= 13) and
                (0 <= int(params['coordinate_y']) <= 13)):
            self.__send(
                self.__message_parser.encode('report', {'status': '32'}))
            return

        # not in any game
        if self.__game is None:
            self.__send(
                self.__message_parser.encode('report', {'status': '43'}))
            return

        # check if it's actually your turn
        if self.__lobby_model.get_game(
                self.__game).get_turn() != self.__player:
            self.__send(
                self.__message_parser.encode('report', {'status': '41'}))
            return

        # save move
        updated = self.__lobby_model.get_game(self.__game).nuke(
            self.__player, params['coordinate_x'], params['coordinate_y'])

        # special attack failed
        if updated is False:
            self.__send(
                self.__message_parser.encode('report', {'status': '32'}))
            return

        logging.debug("Nuke: updated {} fields.".format(len(updated)))
        #if len(updated) == 0:
        #    self.__send(self.__message_parser.encode('report', {'status': '32'}))
        #    return

        # successful special attack
        self.__send(self.__message_parser.encode('report', {'status': '24'}))

        # check if game over
        self.__lobby_model.get_game(self.__game).check_if_game_over(
            self.__player)

    def __move(self, params):
        if not self.__expect_parameter(['ship_id', 'direction'], params):
            return

        # not in any game
        if self.__game is None:
            self.__send(
                self.__message_parser.encode('report', {'status': '43'}))
            return

        # check if it's actually your turn
        if self.__lobby_model.get_game(
                self.__game).get_turn() != self.__player:
            self.__send(
                self.__message_parser.encode('report', {'status': '41'}))
            return

        # save move
        result = self.__lobby_model.get_game(self.__game).move_ship(
            self.__player, int(params['ship_id']), params['direction'])
        if result is False:
            self.__send(
                self.__message_parser.encode('report', {'status': '31'}))
            return

        # successful move
        self.__send(self.__message_parser.encode('report', {'status': '21'}))

    def __surrender(self):
        # not in any game
        if self.__game is None:
            self.__send(
                self.__message_parser.encode('report', {'status': '43'}))
            return

        # make sure the game is ongoing
        if not self.__lobby_model.get_game(self.__game).is_ongoing():
            self.__send(
                self.__message_parser.encode('report', {'status': '43'}))
            return

        # surrender
        self.__lobby_model.get_game(self.__game).surrender(self.__player)

        # surrender accepted lol
        self.__send(self.__message_parser.encode('report', {'status': '23'}))

    def __begin_turn(self):
        self.__send(self.__message_parser.encode('report', {'status': '11'}))

    def __chat(self, params):
        if not self.__expect_parameter(['text'], params):
            return
        self.__lobby_model.chat(self.__id, params['text'])

    def __unknown_msg(self):
        self.__send(self.__message_parser.encode('report', {'status': '40'}))

    def __expect_parameter(self, expected, actual):
        keys = list(actual.keys())
        for p in expected:
            if p not in keys:
                self.__unknown_msg()
                return False
        return True

    def __recv(self, count):
        try:
            msg = self.__socket.recv(count)
        except socket.error as e:
            logging.debug("Client already dead: ".format(repr(e)))
            return
        logging.debug(b"Raw in: " + msg)
        return msg

    def __send(self, msg):
        try:
            self.__socket.sendall(msg)
        except socket.error as e:
            logging.debug("Client already dead: ".format(repr(e)))
            return
        logging.debug(b"Raw out: " + msg)
Example #15
0
class GameState(object):
    def __init__(self, message):
        self.message_parser = MessageParser(message)
        # hole, [['2c', '2d'],...] for 6 players
        self.hole = self.message_parser.hole
        # board ['2c', '2d', '2h', ...] for at most 5 board cards
        self.board = self.message_parser.board
        self.viewing_player = self.message_parser.get_position()
        self.betting_string = self.message_parser.get_betting_string(rd=None)
        self.board_string = self.message_parser.get_board_string(rd=None)
        # a two-dimension list, dim-1 is round, dim-2 is i-th action of a round
        self.betting_action = self.get_betting_action()
        # a one-dimension list, store each {action string} as an element
        self.action_list = []
        # store each {action object} of all round actions in a one-dimension list
        for each_round_action in self.betting_action:
            for action in each_round_action:
                self.action_list.append(Action(action))
        # set up basic data structure
        self.spent = [50, 100, 0, 0, 0, 0]
        self.active = [True] * 6
        self.fold = [False] * 6
        self.allin = [False] * 6
        self.pot = 150
        self.max_bet = 100

        self.current_player = 2  # player at seat 2 is first player to act in PREFLOP round
        self.finished = False
        self.round = Round.PREFLOP
        self.boards = None  # first round have no board cards
        self.holes = None  # hole array for 6 players
        self.min_no_limit_raise_to = 2 * 100
        self.max_no_limit_raise_to = 20000

        self.next_round_flag = False

        self.call_number = 0

        # update [hole] and [board]
        self.holes = self.message_parser.get_hole_card(position=None)
        self.boards = self.message_parser.get_board_card(rd=None)

        # after setting up basic data structure, start to do each action and update data structure
        cnt = 0
        for action in self.action_list:
            cnt += 1
            self.do_action(action)

    def do_action(self, action):
        # [1.0] do action, update player [spent] and [active]
        if action.type == ActionType.CALL:
            self.spent[self.current_player] = self.max_bet
            self.call_number += 1
            # if current player called ALLIN action -> not active
            if self.max_bet == 20000:
                self.active[self.current_player] = False
                self.allin[self.current_player] = True

        #if current player folded -> not active
        elif action.type == ActionType.FOLD:
            self.active[self.current_player] = False
            self.fold[self.current_player] = True

        else:  # must be a raise action
            self.call_number = 1
            # a raise action happened, min_no_limit_raise_to need to be updated
            if action.amount + action.amount - max(
                    self.spent) > self.min_no_limit_raise_to:
                self.min_no_limit_raise_to = action.amount + action.amount - max(
                    self.spent)
            # make sure it <= 20000
            self.min_no_limit_raise_to = min(
                [self.min_no_limit_raise_to, 20000])
            # update {max_bet}
            self.max_bet = action.amount
            self.spent[self.current_player] = action.amount
            # if current player raised to stack size -> not active
            if action.amount == 20000:
                self.active[self.current_player] = False
                self.allin[self.current_player] = True

        # if all players choose all in, then game ends, which no active players
        if self.active.count(True) == 0:
            self.finished = True
            return

        # [3.0] if all active player spent same amount, which means they are reaching next round
        amount_set = set()
        for p, amount in zip(self.active, self.spent):
            if p:
                amount_set.add(amount)
        next_round_reaching_flag = len(
            amount_set) == 1 and self.call_number == self.fold.count(False)
        self.next_round_flag = next_round_reaching_flag
        if next_round_reaching_flag:
            # reset call number
            self.call_number = 0
            # we are going to reach next round
            # if current round == 4, then there is no more next round and the game ends here
            if self.round == Round.RIVER:
                self.finished = True

            # there are next round
            else:
                # update round
                self.round += 1
                # update min_no_limit_raise_to
                self.min_no_limit_raise_to += self.max_bet
                self.min_no_limit_raise_to = min(
                    [self.min_no_limit_raise_to, 20000])
                # find next active player from seat 0
                next_player = 0
                while not self.active[next_player]:
                    next_player = (next_player + 1) % 6
                self.current_player = next_player
        else:
            # we are still at current round
            # update {current player}, find next active player

            # if more than one active player left, find next active player
            if self.active.count(True) > 1:
                # game is not finished yet
                # find next active player
                next_player = (self.current_player + 1) % 6
                while not self.active[next_player]:
                    next_player = (next_player + 1) % 6
                self.current_player = next_player
            elif self.active.count(True) == 1:
                # game may finish now
                # if there is no all-in player, which means other players all folded, only one player left
                if self.allin.count(True) == 0:
                    # game ends
                    self.finished = True
                # else, there are all-in player, the only one player who is active is the next current player
                else:
                    self.current_player = self.active.index(True)
            else:
                # active player number is 0, which means they are at least one player all-in, the rest are folded
                # game is finished
                self.finished = True

    # split betting string into single betting actions
    # if rd=None, by default, handle betting string of all rounds
    def get_betting_action(self, rd=None):
        pattern = re.compile(r'r\d+|f|c')
        if rd is not None:
            string = self.betting_string[rd]
            current_round_action = []
            # parse string into sigle action string
            for m in pattern.finditer(string):
                current_round_action.append(m.group())
            return current_round_action
        else:
            betting_action = []
            for string in self.betting_string:
                # parse string into single action string
                current_round_action = []
                for m in pattern.finditer(string):
                    current_round_action.append(m.group())
                betting_action.append(current_round_action)
            return betting_action

    # who just did an action
    def get_current_player(self):
        return self.current_player

    # return active player
    # a list containing True/False
    def get_active_player(self):
        return self.active

    def get_active_player_number(self):
        return self.active.count(True)

    def get_max_bet(self):
        return self.max_bet

    def get_min_bet(self):
        return self.min_bet

    def get_pot(self):
        return sum(self.pot)

    def get_next_valid_raise_size(self):
        return [self.min_no_limit_raise_to, self.max_no_limit_raise_to]

    def is_my_turn(self):
        return self.viewing_player == self.current_player
Example #16
0
class ServerConnection(object):
    """
    Class handling irc servers.
    """
    PING_INTERVAL_THRESHOLD = 300  # 300 seconds

    def __init__(self, networkname, server_config, bot_config, joinlist, modules_config):
        self.alive = True
        self.connected = False
        self.hostname = server_config['hostname']
        self.port = int(server_config.get('port', "6667"))
        self.nick = bot_config['nick']
        self.altnick = bot_config.get('altnick', self.nick + "_")
        self.username = bot_config['username']
        self.realname = bot_config['realname']
        self.owner = bot_config['owner']
        self.networkname = networkname

        self.joinlist = joinlist

        self._reader_thread = None
        self._parser = MessageParser()
        self._init_callback_table()
        self._socket = None

        self._channel_list = []

        self._modules_config = modules_config
        self.dynamic_modules = [DynamicModule(self, m, c) for m, c in modules_config.items()]

        self._last_ping = time.time()

    def _init_callback_table(self):
        self._receive_callbacks = {
            MessageType.PRIVATE_MESSAGE: self._private_message_received,
            MessageType.JOIN: self._join_received,
            MessageType.PART: self._part_received,
            MessageType.PING: self._ping_received,
            MessageType.QUIT: self._quit_received,
            MessageType.TOPIC: self._topic_received,
            MessageType.END_OF_MOTD: self._motd_received,
            #MessageType.NICK_IN_USE: self.ni,
            MessageType.TOPIC_REPLY: self._topic_reply_received,
            MessageType.USERS: self._users_received,
            MessageType.END_OF_USERS: self._users_end_received,
            MessageType.CHANNEL_MESSAGE: self._channel_message_received,
            MessageType.UNKNOWN: self._unknown_message_received,
            MessageType.CTCP_TIME: self._ctcp_message_received,
            MessageType.CTCP_VERSION: self._ctcp_version_received,
            MessageType.CTCP_PING: self._ctcp_message_received,
            MessageType.CTCP_DCC: self._ctcp_message_received,
        }

    def connect(self):
        """
        Tries to connect to irc server.
        """
        self._reader_thread = Thread(target=self._connection_loop)
        self._reader_thread.start()

    def _connect(self):
        while self.alive:
            try:
                if self._socket:
                    self._socket.close()

                self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                self._socket.connect((self.hostname, self.port))

                self.NICK(self.nick)
                self.USER(self.username, self.realname)

                self._last_ping = time.time()

                break

            except Exception as e:
                self._print_line(str(e) + " " + self.hostname)
                self._print_line("Trying again in 30 seconds.")
                self._sleep(30)

    def _connection_loop(self):
        while self.alive:
            self._connect()
            self._read()

            if not self.alive:
                break

            self._print_line("Trying again in 60 seconds.")
            self._sleep(60)

    def _write(self, message):
        """
        Prints and writes message to server.
        """
        self._print_line(message[:-1])
        self._socket.send(bytearray(message, 'utf-8'))

    def _check_ping_time(self):
        return time.time() - self._last_ping < ServerConnection.PING_INTERVAL_THRESHOLD

    def _read(self):
        """
        Reads and handles messages.
        """
        self._socket.settimeout(1.0)
        buff = ""
        while self.alive and self._check_ping_time():
            try:
                tmp = self._socket.recv(4096)
            except socket.timeout as e:
                continue
            except socket.error as e:
                self._print_line(str(e))
                break
            except KeyboardInterrupt:
                self.kill()
                return

            if not self.alive:
                break

            if not tmp:
                break

            tmp = tmp.decode('utf-8')

            buff += tmp
            parsed_messages, remainder = self._parser.parse_buffer(buff)
            buff = remainder
            self._handle_messages(parsed_messages)

        self._socket.close()
        self._print_line("Connection closed.")
        self.connected = False

    def _handle_messages(self, messages):
        """
        Handles a list of messages
        """
        for message in messages:
            self._receive_callbacks[message.type](**message.params)

    def _print_line(self, message):
        """
        Prints message with timestamp.
        """
        print(time.strftime("%H:%M:%S") + " |" + self.networkname + "| " + message)

    def NICK(self, nick):
        """
        Sets user's nick on server.
        """
        self._write("NICK " + nick + "\r\n")

    def USER(self, username, realname):
        """
        Sets username and realname to server on connect.
        """
        self._write("USER " + username + " 0 * :" + realname + "\r\n")

    def PONG(self, message):
        """
        Reply to PING.
        """
        self._write("PONG :" + message + "\r\n")

    def JOIN(self, channel):
        """
        Joins a irc channel.
        """
        self._write("JOIN :" + channel + "\r\n")

    def PART(self, channel, reason=""):
        """
        PARTs from a channel.
        """
        msg = "PART " + channel
        if reason:
            msg += " :" + reason
        self._write(msg + "\r\n")

    def PRIVMSG(self, target, message):
        """
        Sends PRIVMSG to target.
        """
        self._write("PRIVMSG " + target + " :" + message + "\r\n")

    def PING(self, message):
        """
        Sends PING to server.
        """
        self._write("PING " + message + "\r\n")

    def CTCP(self, target, message):
        self.PRIVMSG(target, str("\x01" + message + "\x01"))

    def NOTICE(self, target, message):
        self._write("NOTICE " + target + " :" + message + "\r\n")

    def _on_connect(self):
        """
        Called when connected to the network.
        """
        self.PING(self.hostname)
        self._join_channels()

        for dm in self.dynamic_modules:
            try:
                dm.instance.on_connect()
            except Exception as e:
                print(e)

    def _join_channels(self):
        """
        Joins channels specified in self.joinlist
        """
        for channel in self.joinlist:
            self.JOIN(channel)

    def kill(self):
        """
        Called when the thread is wanted dead.
        """
        self.alive = False
        for m in self.dynamic_modules:
            m.instance.kill()

    def _private_message_received(self, **kw):
        """
        Called when a private message has been received. Prints it
        and calls on_private_message() on DynamicModule instances.
        """
        source = kw['source']
        message = kw['message']
        full_mask = kw['full_mask']
        self._print_line("PRIVATE" + " <" + source + "> " + message)

        for dm in self.dynamic_modules:
            try:
                dm.instance.on_private_message(source, message, full_mask)
            except Exception as e:
                print(e)

    def _channel_message_received(self, **kw):
        """
        Called when a PRIVMSG to a channel has been received. Prints it
        and calls on_channel_message() on DynamicModule instances.
        """

        source = kw['source']
        message = kw['message']
        full_mask = kw['full_mask']
        channel = kw['channel_name']

        self._print_line(channel + " <" + source + "> " + message)

        for dm in self.dynamic_modules:
            try:
                dm.instance.on_channel_message(source, channel, message, full_mask)
            except Exception as e:
                print(e)

    def _ping_received(self, **kw):
        """
        Called when PING message has been received.
        """

        self._last_ping = time.time()
        message = kw['message']
        self.PONG(message)

    def _motd_received(self, **kw):
        """
        Called when the end of MOTD message
        has been received.
        """
        message = kw['message']

        self._print_line(message)
        if not self.connected:
            self.connected = True
            self._on_connect()

    def _find_channel_by_name(self, channel_name):
        """
        Returns a channel instance from channel_list
        matching channel_name parameter or None.
        """
        for channel in self._channel_list:
            if channel.name == channel_name:
                return channel

    def _add_channel(self, name, user_list):
        """
        Adds a channel to networks channel list.
        """
        if self._find_channel_by_name(name):
            return

        channel = IrcChannel(name, user_list)
        self._channel_list.append(channel)

    def _users_received(self, **kw):
        """
        Called when USERS message is received. Notifies
        channel instance of the users.
        """

        channel_name = kw['channel_name']
        user_list = kw['user_list']

        channel = self._find_channel_by_name(channel_name)
        if not channel:
            self._add_channel(channel_name, user_list)
            return

        channel.users_message(user_list)

    def _users_end_received(self, **kw):
        """
        Called when USERS message's end has been received.
        Notifies the channel instance.
        """

        channel_name = kw['channel_name']

        channel = self._find_channel_by_name(channel_name)
        if not channel:
            # TODO FIX
            self._print_line("REPORT THIS: usersEndReceived, channel not found")
            return

        channel.users_message_end()
        self._print_line("USERS OF " + channel_name)
        self._print_line(" ".join(channel.userlist))

    def _quit_received(self, **kw):
        """
        Called when a QUIT message has been received. Calls
        on_quit() on DynamicModules
        """

        nick = kw['nick']
        full_mask = kw['full_mask']

        for channel in self._channel_list:
            channel.remove_user(nick)

        self._print_line(nick + " has quit.")

        for dm in self.dynamic_modules:
            try:
                dm.instance.on_quit(nick, full_mask)
            except Exception as e:
                print(e)

    def _part_received(self, **kw):
        """
        Called when a PART message has been received. Calls
        on_part() on DynamicModules
        """

        nick = kw['nick']
        channel_name = kw['channel_name']
        full_mask = kw['full_mask']

        channel = self._find_channel_by_name(channel_name)
        if not channel:
            return

        channel.remove_user(nick)

        self._print_line(nick + " has parted " + channel_name)

        for dm in self.dynamic_modules:
            try:
                dm.instance.on_part(nick, channel_name, full_mask)
            except Exception as e:
                print(e)

    def _join_received(self, **kw):
        """
        Called when a JOIN message has been received. Calls
        on_join() on DynamicModules
        """

        nick = kw['nick']
        channel_name = kw['channel_name']
        full_mask = kw['full_mask']

        channel = self._find_channel_by_name(channel_name)
        if channel:
            channel.add_user(nick)

        self._print_line(nick + " has joined " + channel_name)
        for dm in self.dynamic_modules:
            try:
                dm.instance.on_join(nick, channel_name, full_mask)
            except Exception as e:
                print(e)

    def _topic_received(self, **kw):
        """
        Called when topic is changed on a channel. Calls on_topic()
        on DynamicModules
        """

        nick = kw['nick']
        channel_name = kw['channel_name']
        full_mask = kw['full_mask']
        topic = kw['topic']

        channel = self._find_channel_by_name(channel_name)
        if channel:
            channel.topic = topic

        self._print_line(nick + " changed the topic of " + channel_name + " to: " + topic)
        for dm in self.dynamic_modules:
            try:
                dm.instance.on_topic(nick, channel_name, topic, full_mask)
            except Exception as e:
                print(e)

    def _topic_reply_received(self, **kw):
        """
        Called when server responds to client's /topic or server informs
        of the topic on joined channel.
        """

        channel_name = kw['channel_name']
        topic = kw['topic']

        channel = self._find_channel_by_name(channel_name)
        if channel:
            channel.topic = topic

        self._print_line("Topic in " + channel_name + ": " + topic)

    def _ctcp_message_received(self, **kw):
        self._print_line("CTCP: " + str(kw))

    def _ctcp_version_received(self, **kw):
        ":[email protected] NOTICE irckaaja :VERSION ?l? hakkeroi!"
        self.NOTICE(kw['source'], "\x01VERSION irckaaja 0.1.0\x01")

    def _unknown_message_received(self, **kw):
        self._print_line(kw['message'])

    def _sleep(self, seconds):
        """
        Sleeps for seconds unless not self.alive.
        """
        start = time.time()
        while time.time() < start + seconds and self.alive:
            time.sleep(1)
Example #17
0
import json, sys, socket, time

sys.path.insert(0, './lib')
from irccontroller import SlackIRCController
from messageparser import MessageParser

with open('config.json', 'r') as cfg:
    config = json.load(cfg)

slackbot = SlackIRCController(server=config['irc']['host'],
                              port=config['irc']['port'],
                              channel=config['irc']['channel'],
                              master=config['master'],
                              parser=MessageParser(config=config),
                              username=config['irc']['username'],
                              password=config['irc']['password'])


# Runs the bot and handles/retries on connection errors,
# implementing an exponential backoff up to 256 seconds.
def retryLoop(func, sec):
    try:
        func()
    except socket.error:
        sec = sec + 1 if sec < 8 else 1
        print 'Connection error, retrying in ' + str(2**sec) + ' seconds...'
        time.sleep(2**sec)
        retryLoop(func, sec)


retryLoop(slackbot.run, 0)