def get_me(self): try: msg = self.sender.get_self() return User(msg.peer_id, msg.first_name, None, msg.username) except Exception as e: catch_exception(e, self.bot) return None
def convert_message(self, msg): try: # logging.info(msg) id = msg.id extra = {} content = msg.content type = 'text' date = time() logging.info('%s - %s' % (time(), mktime(msg.created_at.timetuple()))) reply = None sender = User(msg.author.id, msg.author.name, '#' + msg.author.discriminator, msg.author.name + '#' + msg.author.discriminator, msg.author.bot) conversation = Conversation(msg.channel.id) if hasattr(msg.channel, 'name'): conversation.id = -msg.channel.id conversation.title = msg.channel.name elif hasattr(msg.channel, 'recipient'): conversation.id = msg.channel.recipient.id conversation.title = msg.channel.recipient.name return Message(id, conversation, sender, content, type, date, reply, extra) except Exception as e: logging.error(e) catch_exception(e, self.bot)
def receiver_worker(self): logging.debug('Starting receiver worker...') try: self.receiver.start() self.receiver.message(self.main_loop()) except Exception as e: catch_exception(e, self.bot)
async def on_message(message): # don't respond to ourselves if message.author.id == self.bot.info.id: return msg = self.convert_message(message) try: logging.info( '[%s] %s@%s [%s] sent [%s] %s' % (msg.sender.id, msg.sender.first_name, msg.conversation.title, msg.conversation.id, msg.type, msg.content)) except AttributeError: logging.info( '[%s] %s@%s [%s] sent [%s] %s' % (msg.sender.id, msg.sender.title, msg.conversation.title, msg.conversation.id, msg.type, msg.content)) try: if msg.content.startswith('/') or msg.content.startswith(self.bot.config.prefix): if int(msg.conversation.id) > 0: chat = self.client.get_user(msg.conversation.id) else: chat = self.client.get_channel(positive(msg.conversation.id)) await chat.trigger_typing() self.bot.on_message_receive(msg) while self.bot.outbox.qsize() > 0: msg = self.bot.outbox.get() logging.info(' [%s] %s@%s [%s] sent [%s] %s' % (msg.sender.id, msg.sender.first_name, msg.conversation.title, msg.conversation.id, msg.type, msg.content)) await self.send_message(msg) except KeyboardInterrupt: pass except Exception as e: logging.error(e) if self.bot.started: catch_exception(e, self.bot)
async def send_message(self, message): try: if int(message.conversation.id) > 0: chat = self.client.get_user(message.conversation.id) else: chat = self.client.get_channel(positive(message.conversation.id)) await chat.trigger_typing() if message.type == 'text': content = self.add_discord_mentions(chat, message.content) if message.extra: if 'format' in message.extra and message.extra['format'] == 'HTML': content = html_to_discord_markdown(content) if 'preview' in message.extra and not message.extra['preview']: content = re.sub(r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', r'<\g<0>>', content, flags=re.MULTILINE) if len(content) > 2000: texts = split_large_message(content, 2000) for text in texts: await chat.send(text) else: await chat.send(content) elif message.type == 'photo' or message.type == 'document' or message.type == 'video' or message.type == 'voice': send_content = True embed = Embed() if message.extra and 'caption' in message.extra and message.extra['caption']: lines = message.extra['caption'].split('\n') embed.title = lines[0] embed.description = '\n'.join(lines[1:]) send_content = False if send_content: if message.content.startswith('/'): await chat.send(file=discord.File(message.content, filename=message.type + get_extension(message.content))) else: await chat.send(message.content) else: if message.content.startswith('/'): await chat.send(file=discord.File(message.content, filename=message.type + get_extension(message.content)), embed=embed) elif message.content.startswith('http'): if message.type == 'photo': embed.set_image(url=message.content) elif message.type == 'video': embed.set_video(url=message.content) else: embed.url = message.content await chat.send(embed=embed) except KeyboardInterrupt: pass except Exception as e: logging.error(e) if self.bot.started: catch_exception(e, self.bot)
def get_bots(): botlist = [] for bot in bots: try: botlist.append(Bot(bot)) except Exception as e: catch_exception(e) logging.error(' [Failed] "%s" failed to initialize' % bot) return botlist
def check_trigger(self, command, parameters, message, plugin, friendly=False): if isinstance(command, str): command = command.lower() if isinstance(message.content, str) and message.content.endswith( '@' + self.info.username) and ' ' not in message.content: message.content = message.content.replace( '@' + self.info.username, '') # If the commands are not /start or /help, set the correct command start symbol. # if ((command == '/start' and '/start' in message.content) or (command == '/help' and '/help' in message.content)): trigger = command.replace('/', '^/') else: if message.type == 'inline_query': trigger = command.replace('/', '^') else: trigger = command.replace('/', '^' + self.config.prefix) if not friendly: # trigger = trigger.replace('@' + self.info.username.lower(), '') if not parameters and trigger.startswith('^'): trigger += '$' elif parameters and ' ' not in message.content and not message.reply: trigger += '$' elif parameters and ' ' in message.content: trigger += ' ' try: if message.content and isinstance( message.content, str) and re.compile( trigger, flags=re.IGNORECASE).search( message.content): set_input(message, trigger) if message.type == 'inline_query': if hasattr(plugin, 'inline'): plugin.inline(message) else: plugin.run(message) return True except Exception as e: catch_exception(e, self) self.send_message(message, self.trans.errors.exception_found, extra={'format': 'HTML'}) return False return False
def cron_jobs(self): while (self.started): for plugin in self.plugins: try: if hasattr(plugin, 'cron'): plugin.cron() except KeyboardInterrupt: pass except Exception as e: catch_exception(e, self) sleep(5)
def receiver_worker(self): logging.debug('Starting receiver worker...') def get_updates(offset=None, limit=None, timeout=None): params = {} if offset: params['offset'] = offset if limit: params['limit'] = limit if timeout: params['timeout'] = timeout return self.api_request('getUpdates', params) try: last_update = 0 while self.bot.started: res = get_updates(last_update + 1) if res and 'result' in res: result = res.result for u in result: if u.update_id > last_update: last_update = u.update_id if 'inline_query' in u: message = self.convert_inline(u.inline_query) self.bot.inbox.put(message) elif 'message' in u: message = self.convert_message(u.message) self.bot.inbox.put(message) elif 'edited_message' in u: message = self.convert_message( u.edited_message) self.bot.inbox.put(message) elif 'channel_post' in u: message = self.convert_message(u.channel_post) self.bot.inbox.put(message) elif 'edited_channel_post' in u: message = self.convert_message( u.edited_channel_post) self.bot.inbox.put(message) except KeyboardInterrupt: pass except Exception as e: if self.bot.started: catch_exception(e, self.bot)
def sender_worker(self): try: logging.debug('Starting sender worker...') while self.started: msg = self.outbox.get() logging.info(' %s@%s sent [%s] %s' % (msg.sender.first_name, msg.conversation.title, msg.type, msg.content)) self.bindings.send_message(msg) except KeyboardInterrupt: pass except Exception as e: catch_exception(e, self)
async def cron_task(self): await self.wait_until_ready() while not self.is_closed() and self.started: for plugin in self.plugins: try: if hasattr(plugin, 'cron'): plugin.cron() except KeyboardInterrupt: pass except Exception as e: catch_exception(e, self) await asyncio.sleep(5) logging.info('is closed')
def get_database(self): try: self.config = wait_until_received('bots/' + self.name) self.trans = wait_until_received('translations/' + self.config['translation']) self.users = wait_until_received('users/' + self.name) self.groups = wait_until_received('groups/' + self.name) self.steps = wait_until_received('steps/' + self.name) self.tags = wait_until_received('tags/' + self.name) self.settings = wait_until_received('settings/' + self.name) self.administration = wait_until_received('administration/' + self.name) self.pins = wait_until_received('pins/' + self.name) self.reminders = wait_until_received('reminders/' + self.name) self.poles = wait_until_received('poles/' + self.name) except Exception as e: catch_exception(e, self)
def main_loop(self): while self.bot.started: try: msg = (yield) if (msg.event == 'message' and msg.own == False) or msg.event == 'service': message = self.convert_message(msg) self.bot.inbox.put(message) if message.conversation.id > 0: self.sender.mark_read(self.peer(message.sender.id)) else: self.sender.mark_read( self.peer(message.conversation.id)) except Exception as e: catch_exception(e, self.bot)
def messages_handler(self): try: logging.debug('Starting message handler...') while self.started: msg = self.inbox.get() try: logging.info( '%s@%s sent [%s] %s' % (msg.sender.first_name, msg.conversation.title, msg.type, msg.content)) except AttributeError: logging.info('%s@%s sent [%s] %s' % (msg.sender.title, msg.conversation.title, msg.type, msg.content)) self.on_message_receive(msg) except KeyboardInterrupt: pass except Exception as e: catch_exception(e, self)
def send_message(self, message): try: if not message.extra: message.extra = {} if message.type != 'text' and message.content.startswith('http'): message.content = download(message.content) elif message.type != 'text' and not message.content.startswith( '/'): message.content = self.sender.load_file(message.content) if not message.extra or not 'caption' in message.extra: message.extra['caption'] = None if message.type == 'text': self.sender.send_typing(self.peer(message.conversation.id), 1) if 'format' in message.extra and message.extra[ 'format'] == 'Markdown': message.content = remove_markdown(message.content) elif 'format' in message.extra and message.extra[ 'format'] == 'HTML': message.content = self.convert_links(message.content) if 'format' in message.extra and message.extra[ 'format'] == 'HTML': self.sender.raw('[html] msg %s %s' % (self.peer(message.conversation.id), self.escape(message.content)), enable_preview=False) else: self.sender.send_msg(self.peer(message.conversation.id), message.content, enable_preview=False) elif message.type == 'photo': self.sender.send_typing(self.peer(message.conversation.id), 1) # 7 if message.reply: self.sender.reply_photo(message.reply, message.content, message.extra['caption']) else: self.sender.send_photo(self.peer(message.conversation.id), message.content, message.extra['caption']) elif message.type == 'audio': self.sender.send_typing(self.peer(message.conversation.id), 1) # 6 if message.reply: self.sender.reply_audio(message.reply, message.content) else: self.sender.send_audio(self.peer(message.conversation.id), message.content) elif message.type == 'document': self.sender.send_typing(self.peer(message.conversation.id), 1) # 8 if message.reply: self.sender.reply_document(message.reply, message.content) else: self.sender.send_document( self.peer(message.conversation.id), message.content) elif message.type == 'sticker': if message.reply: self.sender.reply_file(message.reply, message.content) else: self.sender.send_file(self.peer(message.conversation.id), message.content) elif message.type == 'video': self.sender.send_typing(self.peer(message.conversation.id), 1) # 4 if message.reply: self.sender.reply_video(message.reply, message.content) else: self.sender.send_video(self.peer(message.conversation.id), message.content) elif message.type == 'voice': self.sender.send_typing(self.peer(message.conversation.id), 5) if message.reply: self.sender.reply_audio(message.reply, message.content) else: self.sender.send_audio(self.peer(message.conversation.id), message.content) elif message.type == 'location': self.sender.send_typing(self.peer(message.conversation.id), 1) # 9 if message.reply: self.sender.reply_location(message.reply, message.content['latitude'], message.content['longitude']) else: self.sender.send_location( self.peer(message.conversation.id), message.content['latitude'], message.content['longitude']) else: print('UNKNOWN MESSAGE TYPE: ' + message.type) logging.debug("UNKNOWN MESSAGE TYPE") except Exception as e: catch_exception(e, self.bot)
def on_message_receive(self, msg): try: ignore_message = False if msg.content == None or (msg.type != 'inline_query' and msg.date < time() - 60 * 5): return # if msg.sender.id != self.config['owner'] and not is_trusted(self, msg.sender.id, msg) and (has_tag(self, msg.conversation.id, 'spam') or has_tag(self, msg.sender.id, 'spam')): # ignore_message = True # self.send_message(msg, self.trans.errors.spammer_detected, extra={'format': 'HTML'}) if msg.sender.id != self.config['owner'] and not is_trusted( self, msg.sender.id, msg) and (has_tag(self, msg.conversation.id, 'muted') or has_tag(self, msg.sender.id, 'muted')): ignore_message = True step = get_step(self, msg.conversation.id) if step: if not ignore_message: for plugin in self.plugins: if get_plugin_name(plugin) == step.plugin and hasattr( plugin, 'steps'): if msg.content.startswith('/cancel'): plugin.steps(msg, -1) cancel_steps(self, msg.conversation.id) if msg.content.startswith('/done'): plugin.steps(msg, 0) cancel_steps(self, msg.conversation.id) else: plugin.steps(msg, step['step']) else: for plugin in self.plugins: # Always do this action for every message. # if hasattr(plugin, 'always'): plugin.always(msg) # If no query show help # if msg.type == 'inline_query' and not ignore_message: if msg.content == '': msg.content = 'help' if hasattr(plugin, 'commands') and not ignore_message: # Check if any command of a plugin matches. # for command in plugin.commands: if 'parameters' not in command: command['parameters'] = None if 'command' in command: if self.check_trigger(command['command'], command['parameters'], msg, plugin): break if 'keep_default' in command and command[ 'keep_default']: if self.check_trigger( command['command'], command['parameters'], msg, plugin, False, True): break if 'friendly' in command and not has_tag( self, msg.sender.id, 'noreplies' ) and not has_tag( self, msg.conversation.id, 'noreplies' ) and msg.conversation.id != self.config.alerts_conversation_id and msg.conversation.id != self.config.admin_conversation_id: if self.check_trigger(command['friendly'], command['parameters'], msg, plugin, True): break if 'shortcut' in command: if self.check_trigger(command['shortcut'], command['parameters'], msg, plugin): break if 'keep_default' in command and command[ 'keep_default']: if self.check_trigger( command['shortcut'], command['parameters'], msg, plugin, False, True): break except KeyboardInterrupt: pass except Exception as e: catch_exception(e, self)
def run(self, m): input = get_input(m, ignore_reply=False) if not input: return self.bot.send_message(m, generate_command_help(self, m.content), extra={'format': 'HTML'}) # return self.bot.send_message(m, self.bot.trans.errors.missing_parameter, extra={'format': 'HTML'}) status, values = get_coords(input, self.bot) if status == 'ZERO_RESULTS' or status == 'INVALID_REQUEST': return self.bot.send_message(m, self.bot.trans.errors.api_limit_exceeded, extra={'format': 'HTML'}) elif status == 'OVER_DAILY_LIMIT': return self.bot.send_message(m, self.bot.trans.errors.no_results, extra={'format': 'HTML'}) elif status == 'REQUEST_DENIED': return self.bot.send_message(m, self.bot.trans.errors.connection_error, extra={'format': 'HTML'}) lat, lon, locality, country = values url = 'https://api.openweathermap.org/data/2.5/weather' params = { 'APPID': self.bot.config.api_keys.open_weather, 'lon': lon, 'lat': lat, 'units': 'metric', 'lang': 'es' } data = send_request(url, params, bot=self.bot) logging.info(data) if not data or data.cod != 200: return self.bot.send_message(m, self.bot.trans.errors.no_results, extra={'format': 'HTML'}) title = self.bot.trans.plugins.weather.strings.title % ( locality, country) # weather_string = weather.weather.title() #weather_string = str(self.bot.trans.plugins.weather.strings[data.weather.id]) weather_string = data.weather[0].main weather_icon = self.get_weather_icon(data.weather[0].icon) temp = round(data.main.temp, 1) humidity = data.main.humidity wind = data.wind.speed feelslike = '' # try: # temp_c = mc.Temp(data.main.temp, 'c') # feelslike_c = round(mc.heat_index(temperature=temp_c, humidity=humidity), 1) # if (float(feelslike_c) - float(data.main.temp)) > 0.001: # feelslike = self.bot.trans.plugins.weather.strings.feelslike % feelslike_c # except: # pass if is_command(self, 1, m.content): message = u'%s\n%s %s%s\n🌡%sºC 💧%s%% 🌬%s m/s' % ( remove_html(title), weather_icon, weather_string, feelslike, temp, humidity, wind) try: photo = get_streetview( lat, lon, self.bot.config.api_keys.google_developer_console) except Exception as e: catch_exception(e, self.bot) photo = None if photo: return self.bot.send_message(m, photo, 'photo', extra={'caption': message}) else: return self.bot.send_message(m, message, extra={'format': 'HTML'}) elif is_command(self, 2, m.content): return self.bot.send_message(m, self.bot.trans.errors.not_implemented, extra={'format': 'HTML'})
def send_message(self, message): try: self.send_chat_action(message.conversation.id, message.type) data = None input_message_content = None if message.type == 'text': if not message.content or (isinstance(message.content, str) and len(message.content) == 0): return if message.extra and 'format' in message.extra: if message.extra['format'] == 'HTML': parse_mode = 'textParseModeHTML' else: parse_mode = 'textParseModeMarkdown' formated_text = self.server_request( 'parseTextEntities', { 'text': message.content, 'parse_mode': { '@type': parse_mode } }) if formated_text: text = formated_text else: text = { '@type': 'formattedText', 'text': message.content, 'entities': [] } else: text = { '@type': 'formattedText', 'text': message.content, 'entities': [] } preview = False if message.extra and 'preview' in message.extra: preview = message.extra['preview'] input_message_content = { '@type': 'inputMessageText', 'text': text, 'disable_web_page_preview': not preview } elif message.type == 'photo': input_message_content = { '@type': 'inputMessagePhoto', 'photo': self.get_input_file(message.content) } if message.extra and 'caption' in message.extra: input_message_content['caption'] = { '@type': 'formattedText', 'text': message.extra['caption'] } elif message.type == 'animation': input_message_content = { '@type': 'inputMessageAnimation', 'animation': self.get_input_file(message.content) } if message.extra and 'caption' in message.extra: input_message_content['caption'] = { '@type': 'formattedText', 'text': message.extra['caption'] } elif message.type == 'audio': input_message_content = { '@type': 'inputMessageAudio', 'audio': self.get_input_file(message.content) } if message.extra and 'caption' in message.extra: input_message_content['caption'] = { '@type': 'formattedText', 'text': message.extra['caption'] } elif message.type == 'document': input_message_content = { '@type': 'inputMessageDocument', 'document': self.get_input_file(message.content) } if message.extra and 'caption' in message.extra: input_message_content['caption'] = { '@type': 'formattedText', 'text': message.extra['caption'] } elif message.type == 'sticker': input_message_content = { '@type': 'inputMessageSticker', 'sticker': self.get_input_file(message.content) } elif message.type == 'video': input_message_content = { '@type': 'inputMessageVideo', 'video': self.get_input_file(message.content) } elif message.type == 'voice': input_message_content = { '@type': 'inputMessageVoiceNote', 'voice_note': self.get_input_file(message.content) } if message.extra and 'caption' in message.extra: input_message_content['caption'] = { '@type': 'formattedText', 'text': message.extra['caption'] } elif message.type == 'forward': data = { '@type': 'forwardMessages', 'chat_id': message.extra['conversation'], 'from_chat_id': message.conversation.id, 'message_ids': [message.extra['message']] } elif message.type == 'system': data = { '@type': message.content, 'chat_id': message.conversation.id } if message.extra and 'title' in message.extra: data['title'] = message.extra['title'] if message.extra and 'user_id' in message.extra: data['user_id'] = message.extra['user_id'] if message.extra and 'custom_title' in message.extra: data['custom_title'] = message.extra['custom_title'] if message.extra and 'photo' in message.extra: data['photo'] = self.get_input_file(message.extra['photo']) if message.extra and 'description' in message.extra: data['description'] = message.extra['description'] if message.extra and 'message_id' in message.extra: data['message_id'] = message.extra['message_id'] if message.extra and 'sticker_set_name' in message.extra: data['sticker_set_name'] = message.extra[ 'sticker_set_name'] if message.extra and 'commands' in message.extra: data['commands'] = message.extra['commands'] elif message.type == 'api': files = None params = { "chat_id": message.conversation.id, } if message.extra and 'user_id' in message.extra: params['user_id'] = message.extra['user_id'] if message.extra and 'custom_title' in message.extra: params['custom_title'] = message.extra['custom_title'] if message.extra and 'photo' in message.extra: if message.extra['photo'].startswith('/'): photo = open(message.extra['photo'], 'rb') files = {'photo': photo} else: params['photo'] = message.extra['photo'] if message.extra and 'message_id' in message.extra: params['message_id'] = message.extra['message_id'] if message.extra and 'sticker_set_name' in message.extra: params['sticker_set_name'] = message.extra[ 'sticker_set_name'] if message.extra and 'commands' in message.extra: params['commands'] = message.extra['commands'] self.api_request(message.content, params, files=files) self.send_chat_action(message.conversation.id, 'cancel') return if input_message_content: data = { '@type': 'sendMessage', 'chat_id': message.conversation.id, 'input_message_content': input_message_content } if message.reply: data['reply_to_message_id'] = message.reply if data: if message.type == 'text' and len( data['input_message_content']['text']['text']) > 4000: texts = split_large_message( data['input_message_content']['text']['text'], 4000) for text in texts: data['input_message_content']['text']['text'] = text result = self.server_request(data['@type'], data, process_request=True) else: result = self.server_request(data['@type'], data, process_request=True) self.send_chat_action(message.conversation.id, 'cancel') except KeyboardInterrupt: pass except Exception as e: logging.error('send_message exception: {}'.format(e)) if self.bot.started: catch_exception(e, self.bot)
def convert_message(self, msg): try: # logging.info(msg) id = msg['id'] extra = {} raw_chat = self.server_request('getChat', {'chat_id': msg['chat_id']}) conversation = Conversation(int(msg['chat_id'])) if raw_chat and 'title' in raw_chat: conversation.title = raw_chat['title'] if 'user_id' in msg['sender']: raw_sender = self.server_request( 'getUser', {'user_id': msg['sender']['user_id']}) sender = User(int(msg['sender']['user_id'])) if 'first_name' in raw_sender: sender.first_name = str(raw_sender['first_name']) if 'last_name' in raw_sender: sender.last_name = str(raw_sender['last_name']) if 'username' in raw_sender: sender.username = str(raw_sender['username']) else: sender = User(conversation.id, conversation.title) if msg['content']['@type'] == 'messageText': content = msg['content']['text']['text'] type = 'text' if 'entities' in msg['content']['text']: for entity in msg['content']['text']['entities']: if entity['type']['@type'] == 'textEntityTypeUrl': if 'urls' not in extra: extra['urls'] = [] extra['urls'].append( fix_telegram_link( content[entity['offset']:entity['offset'] + entity['length']])) elif entity['type'][ '@type'] == 'textEntityTypeMention': if 'mentions' not in extra: extra['mentions'] = [] extra['mentions'].append( content[entity['offset']:entity['offset'] + entity['length']]) elif entity['type'][ '@type'] == 'textEntityTypeMentionText': if 'mentions' not in extra: extra['mentions'] = [] extra['mentions'].append(entity['user']['id']) elif entity['type'][ '@type'] == 'textEntityTypeHashtag': if 'hashtags' not in extra: extra['hashtags'] = [] extra['hashtags'].append( content[entity['offset']:entity['offset'] + entity['length']]) elif entity['type'][ '@type'] == 'textEntityTypeCashtag': if 'cashtags' not in extra: extra['cashtags'] = [] extra['cashtags'].append( content[entity['offset']:entity['offset'] + entity['length']]) elif entity['type'][ '@type'] == 'textEntityTypeBotCommand': if 'commands' not in extra: extra['commands'] = [] extra['commands'].append( content[entity['offset']:entity['offset'] + entity['length']]) elif entity['type'][ '@type'] == 'textEntityTypeEmailAddress': if 'emails' not in extra: extra['emails'] = [] extra['emails'].append( content[entity['offset']:entity['offset'] + entity['length']]) elif entity['type'][ '@type'] == 'textEntityTypePhoneNumber': if 'phone_numbers' not in extra: extra['phone_numbers'] = [] extra['phone_numbers'].append( content[entity['offset']:entity['offset'] + entity['length']]) elif msg['content']['@type'] == 'messagePhoto': content = msg['content']['photo']['sizes'][0]['photo'][ 'remote']['id'] type = 'photo' if msg['content']['caption']: extra['caption'] = msg['content']['caption'] elif msg['content']['@type'] == 'messageAnimation': content = msg['content']['animation']['animation']['remote'][ 'id'] type = 'animation' if msg['content']['caption']: extra['caption'] = msg['content']['caption'] elif msg['content']['@type'] == 'messageDocument': content = msg['content']['document']['document']['remote'][ 'id'] type = 'document' if msg['content']['caption']: extra['caption'] = msg['content']['caption'] elif msg['content']['@type'] == 'messageAudio': content = msg['content']['audio']['audio']['remote']['id'] type = 'audio' if msg['content']['caption']: extra['caption'] = msg['content']['caption'] elif msg['content']['@type'] == 'messageVideo': content = msg['content']['video']['video']['remote']['id'] type = 'video' if msg['content']['caption']: extra['caption'] = msg['content']['caption'] elif msg['content']['@type'] == 'messageVoiceNote': content = msg['content']['voice_note']['voice']['remote']['id'] type = 'voice' if msg['content']['caption']: extra['caption'] = msg['content']['caption'] elif msg['content']['@type'] == 'messageSticker': content = msg['content']['sticker']['sticker']['remote']['id'] type = 'sticker' elif msg['content']['@type'] == 'messageChatAddMembers': content = 'new_chat_member' type = 'notification' request = self.client.get_user( msg['content']['member_user_ids'][0]) request.wait() raw_user = request.update extra = { 'user': User(int(msg['content']['member_user_ids'][0])) } if raw_user: if 'first_name' in raw_user: extra['user'].first_name = str(raw_user['first_name']) if 'last_name' in raw_user: extra['user'].last_name = str(raw_user['last_name']) if 'username' in raw_user: extra['user'].username = str(raw_user['username']) elif msg['content']['@type'] == 'messageChatJoinByLink': content = 'new_chat_member' type = 'notification' extra = {'user': sender} elif msg['content']['@type'] == 'messageChatDeleteMember': content = 'left_chat_member' type = 'notification' request = self.client.get_user(msg['content']['user_id']) request.wait() raw_user = request.update extra = {'user': User(int(msg['content']['user_id']))} if raw_user: if 'first_name' in raw_user: extra['user'].first_name = str(raw_user['first_name']) if 'last_name' in raw_user: extra['user'].last_name = str(raw_user['last_name']) if 'username' in raw_user: extra['user'].username = str(raw_user['username']) elif msg['content']['@type'] == 'messageUnsupported': content = 'Message content that is not supported by the client' type = 'unsupported' else: logging.info('UNSUPPORTED MESSAGE TYPE: {}'.format( msg['content']['@type'])) content = msg['content']['@type'] type = 'unsupported' reply = None if 'reply_to_message_id' in msg and msg['reply_to_message_id'] > 0: reply = self.get_message(msg['chat_id'], msg['reply_to_message_id']) if 'forward_info' in msg and msg['forward_info']: extra['from_chat_id'] = msg['forward_info']['from_chat_id'] extra['from_message_id'] = msg['forward_info'][ 'from_message_id'] if 'chat_id' in msg['forward_info']['origin']: extra['from_chat_id'] = msg['forward_info']['origin'][ 'chat_id'] if 'message_id' in msg['forward_info']['origin']: extra['from_message_id'] = msg['forward_info']['origin'][ 'message_id'] if 'sender_user_id' in msg['forward_info']['origin']: extra['from_user_id'] = msg['forward_info']['origin'][ 'sender_user_id'] if 'via_bot_user_id' in msg and msg['via_bot_user_id'] > 0: extra['via_bot_user_id'] = msg['via_bot_user_id'] if 'restriction_reason' in msg and msg['restriction_reason']: extra['restriction_reason'] = msg['restriction_reason'] if 'reply_markup' in msg and msg['reply_markup']: extra['reply_markup'] = msg['reply_markup'] date = msg['date'] return Message(id, conversation, sender, content, type, date, reply, extra) except Exception as e: logging.error('convert_message exception: {}'.format(e)) catch_exception(e, self.bot)
def update_handler(update): if not self.bot.info.is_bot and self.last_chat_update < time( ) - 60 * 5: self.update_chats(load_all=True) if update['message']['is_outgoing']: if update['message']['is_channel_post']: if update['message']['content']['@type'] == 'messageText': return else: return if not self.bot.info.is_bot: self.server_request('openChat', {'chat_id': update['message']['chat_id']}) self.server_request( 'viewMessages', { 'chat_id': update['message']['chat_id'], 'message_ids': [update['message']['id']], 'force_read': True }) if 'message' in update: msg = self.convert_message(update['message']) try: logging.info('[{}] {}@{} [{}] sent [{}] {}'.format( msg.sender.id, msg.sender.first_name, msg.conversation.title, msg.conversation.id, msg.type, msg.content)) except AttributeError: logging.info('[{}] {}@{} [{}] sent [{}] {}'.format( msg.sender.id, msg.sender.title, msg.conversation.title, msg.conversation.id, msg.type, msg.content)) try: if msg.content.startswith('/') or msg.content.startswith( self.bot.config.prefix): self.send_chat_action(msg.conversation.id) self.bot.on_message_receive(msg) if msg.content.startswith('/') or msg.content.startswith( self.bot.config.prefix): self.send_chat_action(msg.conversation.id, 'cancel') while self.bot.outbox.qsize() > 0: msg = self.bot.outbox.get() logging.info(' [{}] {}@{} [{}] sent [{}] {}'.format( msg.sender.id, msg.sender.first_name, msg.conversation.title, msg.conversation.id, msg.type, msg.content)) self.send_message(msg) if not self.bot.info.is_bot: self.server_request( 'closeChat', {'chat_id': update['message']['chat_id']}) except KeyboardInterrupt: pass except Exception as e: logging.error( 'new_message_handler exception: {}'.format(e)) if self.bot.started: catch_exception(e, self.bot) else: logging.info('UNSUPPORTED UPDATE: {}'.format(update))
def receiver_worker(self): logging.debug('Starting receiver worker...') try: self.discord_loop = asyncio.new_event_loop() self.client = discord.Client(loop=self.discord_loop) self.bg_task = self.discord_loop.create_task(self.cron_task()) except Exception as e: logging.error(e) if self.bot.started: catch_exception(e, self.bot) @self.client.event async def on_ready(): self.bot.info = User(self.client.user.id, self.client.user.name, self.client.user.discriminator, self.client.user.name + '#' + self.client.user.discriminator, self.client.user.bot) status = '{}help'.format(self.bot.config.prefix) activity = discord.Activity( type=discord.ActivityType.listening, name=status) await self.client.change_presence(activity=activity) async def on_member_join(self, member): guild = member.guild if guild.system_channel is not None: sender = User(member.id, member.name, '#' + member.discriminator, member.name + '#' + member.discriminator, member.bot) conversation = Conversation(guild.system_channel.id, guild.system_channel.name) extra = { 'user': sender } self.bot.outbox.put(Message(0, conversation, sender, 'new_chat_member', 'notification', time(), None, extra)) @self.client.event async def on_message(message): # don't respond to ourselves if message.author.id == self.bot.info.id: return msg = self.convert_message(message) try: logging.info( '[%s] %s@%s [%s] sent [%s] %s' % (msg.sender.id, msg.sender.first_name, msg.conversation.title, msg.conversation.id, msg.type, msg.content)) except AttributeError: logging.info( '[%s] %s@%s [%s] sent [%s] %s' % (msg.sender.id, msg.sender.title, msg.conversation.title, msg.conversation.id, msg.type, msg.content)) try: if msg.content.startswith('/') or msg.content.startswith(self.bot.config.prefix): if int(msg.conversation.id) > 0: chat = self.client.get_user(msg.conversation.id) else: chat = self.client.get_channel(positive(msg.conversation.id)) await chat.trigger_typing() self.bot.on_message_receive(msg) while self.bot.outbox.qsize() > 0: msg = self.bot.outbox.get() logging.info(' [%s] %s@%s [%s] sent [%s] %s' % (msg.sender.id, msg.sender.first_name, msg.conversation.title, msg.conversation.id, msg.type, msg.content)) await self.send_message(msg) except KeyboardInterrupt: pass except Exception as e: logging.error(e) if self.bot.started: catch_exception(e, self.bot) try: self.client.run(self.bot.config['bindings_token']) except KeyboardInterrupt: pass except Exception as e: logging.error(e) if self.bot.started: catch_exception(e, self.bot)
def on_message_receive(self, msg): try: if msg.content == None or (msg.type != 'inline_query' and msg.date < time() - 60): return if msg.sender.id != self.config['owner'] and ( has_tag(self, msg.conversation.id, 'muted') or has_tag(self, msg.sender.id, 'muted')): return step = get_step(self, msg.conversation.id) if step: for plugin in self.plugins: if get_plugin_name(plugin) == step.plugin and hasattr( plugin, 'steps'): if msg.content.startswith('/cancel'): plugin.steps(msg, -1) cancel_steps(self, msg.conversation.id) if msg.content.startswith('/done'): plugin.steps(msg, 0) cancel_steps(self, msg.conversation.id) else: plugin.steps(msg, step['step']) else: for plugin in self.plugins: # Always do this action for every message. # if hasattr(plugin, 'always'): plugin.always(msg) # If no query show help # if msg.type == 'inline_query': if msg.content == '': msg.content = 'help' # Check if any command of a plugin matches. # for command in plugin.commands: if 'parameters' not in command: command['parameters'] = None if 'command' in command: if self.check_trigger(command['command'], command['parameters'], msg, plugin): break if 'friendly' in command: if self.check_trigger(command['friendly'], command['parameters'], msg, plugin, True): break if 'shortcut' in command: if self.check_trigger(command['shortcut'], command['parameters'], msg, plugin): break except KeyboardInterrupt: pass except Exception as e: catch_exception(e, self)
def kick_conversation_member(self, conversation_id, user_id): try: self.sender.chat_del_user(self.peer(conversation_id), self.peer(user_id)) except Exception as e: catch_exception(e, self.bot)
def convert_message(self, msg): try: id = msg['id'] if msg.receiver.type == 'user': conversation = Conversation(msg.sender.peer_id) conversation.title = msg.sender.first_name else: if msg.receiver.type == 'channel': conversation = Conversation( -int('100' + str(msg.receiver.peer_id))) else: conversation = Conversation(-int(msg.receiver.peer_id)) conversation.title = msg.receiver.title if msg.sender.type == 'user': sender = User(int(msg.sender.peer_id)) if 'first_name' in msg.sender: sender.first_name = msg.sender.first_name if 'last_name' in msg.sender: sender.last_name = msg.sender.last_name if 'username' in msg.sender: sender.username = msg.sender.username else: if msg.sender.type == 'channel': sender = Conversation(-int('100' + str(msg.sender.peer_id))) else: sender = Conversation(-int(msg.sender.peer_id)) sender.first_name = msg.sender.title date = msg.date # Gets the type of the message if 'text' in msg: type = 'text' content = msg.text extra = None elif 'media' in msg: type = msg.media.type content = msg.id if 'caption' in msg.media: extra = msg.media.caption else: extra = None elif msg.event == 'service': type = 'notification' if msg.action.type == 'chat_del_user': content = 'left_chat_member' extra = msg.action.user.peer_id elif msg.action.type == 'chat_add_user': content = 'new_chat_member' extra = msg.action.user.peer_id elif msg.action.type == 'chat_add_user_link': content = 'new_chat_member' extra = msg.sender.peer_id else: type = None content = None extra = None else: type = None content = None extra = None if not extra: extra = {} # Generates another message object for the original message if the reply. if 'reply_id' in msg: reply_msg = self.sender.message_get(msg.reply_id) reply = self.convert_message(reply_msg) else: reply = None return Message(id, conversation, sender, content, type, date, reply, extra) except Exception as e: catch_exception(e, self.bot)