class PSBot(PokemonShowdownBot): def __init__(self): self.do = Command self.gameCommands = GameCommands self.usernotes = MessageDatabase() PokemonShowdownBot.__init__(self, 'ws://sim.smogon.com:8000/showdown/websocket', self.splitMessage) def splitMessage(self, ws, message): if not message: return if '\n' not in message: self.parseMessage(message, '') room = '' msg = message.split('\n') if msg[0].startswith('>'): room = msg[0][1:] msg.pop(0) if room.startswith('battle-'): if room not in self.details['rooms']: # Battle rooms don't need the same interface as chatrooms self.details['rooms'][room] = True if 'leave|{me}'.format(me = self.details['user']) == msg[0]: self.details['rooms'].pop(room) # Go to battle handler instead of regular rooms # (we don't allow commands in battle rooms anyway) for m in msg: self.bh.parse(room, m) return for m in msg: self.parseMessage(m, room) def parseMessage(self, msg, room): if not msg.startswith('|'): return message = msg.split('|') # Logging in if message[1] == 'challstr': print('{name}: Attempting to login...'.format(name = self.details['user'])) self.login(message[3], message[2]) elif message[1] == 'updateuser': if self.details['user'] not in message[2]: return if message[3] not in '1': print('login failed, still guest') print('crashing now; have a nice day :)') exit() if self.details['avatar'] >= 0: self.send('|/avatar {num}'.format(num = self.details['avatar'])) print('{name}: Successfully logged in.'.format(name = self.details['user'])) for room in self.details['joinRooms']: name = [n for n in room][0] # joinRoom entry is a list of dicts self.joinRoom(name, room[name]) # Challenges elif 'updatechallenges' in message[1]: challs = json.loads(message[2]) if challs['challengesFrom']: opp = [name for name, form in challs['challengesFrom'].items()][0] if challs['challengesFrom'][opp] in supportedFormats: self.send('|/accept {name}'.format(name = opp)) else: self.sendPm(opp, 'Sorry, I only accept challenges in Challenge Cup 1v1, Random Battles or Battle Factory :(') # This is a safeguard for l and n in case that a moderation action happen elif 'unlink' == message[1]: return # Joined new room elif 'users' in message[1]: users = ','.join([u[0]+re.sub(r'[^a-zA-z0-9,]', '',u[1:]).lower() for u in message[2].split(',') if message[2].split(',').index(u) > 0]) self.getRoom(room).addUserlist(users) elif 'j' in message[1].lower(): if self.userIsSelf(message[2][1:]): self.details['rooms'][room].rank = message[2][0] self.getRoom(room).doneLoading() user = re.sub(r'[^a-zA-z0-9]', '', message[2]).lower() self.details['rooms'][room].addUser(user, message[2][0]) # If the user have a message waiting, send that message in a pm if self.usernotes.hasMessage(user): self.sendPm(user, self.usernotes.getMessage(user)) elif 'l' in message[1].lower(): if self.userIsSelf(message[2][1:]): return user = re.sub(r'[^a-zA-z0-9]', '', message[2]).lower() self.details['rooms'][room].removeUser(user) elif 'n' in message[1].lower() and len(message[1]) < 3: newName = message[2][0] + re.sub(r'[^a-zA-z0-9]', '', message[2]).lower() oldName = re.sub(r'[^a-zA-z0-9]', '', message[3]).lower() self.details['rooms'][room].renamedUser(oldName, newName) # Chat messages elif 'c' in message[1].lower(): user = {'name':re.sub(r'[^a-zA-z0-9]', '', message[3]).lower(),'group':message[3][0], 'unform': message[3][1:]} room = self.getRoom(room) if room.loading: return if user['name'] not in room.users: return if self.userIsSelf(user['unform']): return if room.moderate and moderation.canPunish(self, room.title): anything = moderation.shouldAct(message[4], user, room.title, message[2]) if anything: action, reason = moderation.getAction(user, anything, message[2]) # If the current rank isn't allowed to roomban, keep hourmuting them if action == 'roomban' and not moderation.canBan(self, room.title): action = 'hourmute' self.log(action, user['name']) self.takeAction(room.title, user['name'], action, reason) if message[4].startswith(self.details['command']) and message[4][1:] and message[4][1].isalpha(): command = self.extractCommand(message[4]) self.log(message[4], user['name']) response, samePlace = '', True # If the command was a chat game and permissions aren't met, kill the game (even if it just started) if command in self.gameCommands: if not room.allowGames: response = 'This room does not support chatgames.' if 'new' in message[4] and command in ['hangman']: response = "Please use Pm to start a hangman game." if not response: response, samePlace = self.do(self, command, room.title, message[4][len(command) + 1:].lstrip(), user) if response == 'NoAnswer': return if self.evalPermission(user) or command in self.gameCommands: if response: self.reply(room.title, user, self.escapeText(response), samePlace) else: self.reply(room.title, user, '{cmd} is not a valid command.'.format(cmd = command), samePlace) elif command in CanPmReplyCommands: self.sendPm(user['name'], self.escapeText(response)) else: self.sendPm(user['name'], 'Please pm the commands for a response.') elif 'pm' in message[1].lower(): user = {'name':re.sub(r'[^a-zA-z0-9]', '', message[2]).lower(),'group':message[2][0], 'unform': message[2][1:]} if self.userIsSelf(user['unform']): return if message[4].startswith('/invite'): if not message[4][8:] == 'lobby': if self.Groups[user['group']] >= 1: self.joinRoom(message[4][8:]) self.log(message[4], user['name']) else: self.sendPm(user['name'], 'Only global voices (+) and up can add me to rooms, sorry :(') if message[4].startswith(self.details['command']) and message[4][1:] and message[4][1].isalpha(): command = self.extractCommand(message[4]) self.log(message[4], user['name']) params = message[4][len(command) + len(self.details['command']):].lstrip() response, where = '', False if command in self.gameCommands: if params.startswith('new,'): room = params[len('new,'):].split(',')[0].replace(' ','') if not self.getRoom(room).allowGames: response = 'This room does not support chat games' else: user['group'] = self.getRoom(room).users[user['name']] response, where = self.do(self, command, room, params, user) self.reply(room, user, response, where) return elif params.startswith('score'): response, where = self.do(self, command, 'pm', params, user) else: response = "Don't try to play games in pm please" if not response: response, where = self.do(self, command, 'room', params, user) if response: self.sendPm(user['name'], response) else: self.sendPm(user['name'], '{cmd} is not a valid command.'.format(cmd = command)) # Tournaments elif 'tournament' == message[1]: if self.getRoom(room).loading: return if 'create' in message[2]: # Tour was created, join it if in supported formats if not self.details['joinTours']: return room = self.getRoom(room) if not room.tour: room.createTour(self.ws) if room.tour and message[3] in supportedFormats: room.tour.joinTour() elif 'end' == message[2]: if not self.getRoom(room).tour: return winner, tier = self.getRoom(room).tour.getWinner(message[3]) if self.details['user'] in winner: self.say(room, 'I won the {form} tournament :o'.format(form = tier)) else: self.say(room, 'Congratulations to {name} for winning :)'.format(name = ', '.join(winner))) self.getRoom(room).endTour() elif 'forceend' in message[2]: self.getRoom(room).endTour() self.say(room, "Aww, now nobody will win :(") else: if self.getRoom(room).tour: self.getRoom(room).tour.onUpdate(message[2:])