From debe9e4979ae8f6d1672d96d571767c7e480e6d0 Mon Sep 17 00:00:00 2001 From: Stuart Travers Date: Mon, 19 Sep 2016 09:04:19 +1000 Subject: [PATCH 1/5] Move connect to after telegram thread starts Improved startup for me by several seconds. --- .../event_handlers/telegram_handler.py | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/pokemongo_bot/event_handlers/telegram_handler.py b/pokemongo_bot/event_handlers/telegram_handler.py index 4b51651a09..8c3ab7d37c 100644 --- a/pokemongo_bot/event_handlers/telegram_handler.py +++ b/pokemongo_bot/event_handlers/telegram_handler.py @@ -108,9 +108,12 @@ def authenticate(self, update): self.chat_handler.sendMessage(chat_id=update.message.chat_id, parse_mode='Markdown', text="Authentication successful, you can now use all commands") return - def run(self): + def run(self): time.sleep(1) while True: + if self._tbot is None: + self.connect() + for update in self._tbot.getUpdates(offset=self.update_id, timeout=10): self.update_id = update.update_id+1 if update.message: @@ -288,6 +291,7 @@ def __init__(self, bot, config): self.whoami = "TelegramHandler" self.config = config self.chat_handler = ChatHandler(self.bot, self.pokemons) + if master == None: self.master = None return @@ -309,6 +313,13 @@ def __init__(self, bot, config): else: # uid not known yet self.bot.logger.info("Telegram master UID not in datastore yet") self.master = master + + self._connect() + + def _connect(self): + self.bot.logger.info("Telegram bot not running. Starting") + self.tbot = TelegramClass(self.bot, self.master, self.pokemons, self.config) + thread.start_new_thread(self.tbot.run) def catch_notify(self, pokemon, cp, iv, params): if params == " ": @@ -324,15 +335,10 @@ def catch_notify(self, pokemon, cp, iv, params): def handle_event(self, event, sender, level, formatted_msg, data): if self.tbot is None: + if DEBUG_ON: + self.bot.logger.info("handle_event Telegram bot not running.") try: - if hasattr(self, "master"): - selfmaster = self.master - else: - selfmaster = None - self.bot.logger.info("Telegram bot not running. Starting") - self.tbot = TelegramClass(self.bot, selfmaster, self.pokemons, self.config) - self.tbot.connect() - thread.start_new_thread(self.tbot.run) + self._connect() except Exception as inst: self.tbot = None self.bot.logger.error("Unable to start Telegram bot; master: {}, exception: {}".format(selfmaster, pprint.pformat(inst))) From 54f368d53db37eec886c9ffe41aad3c6d1cbf9da Mon Sep 17 00:00:00 2001 From: Stuart Travers Date: Mon, 19 Sep 2016 10:57:35 +1000 Subject: [PATCH 2/5] Fixed master identification for events --- .../event_handlers/telegram_handler.py | 85 +++++++------------ 1 file changed, 32 insertions(+), 53 deletions(-) diff --git a/pokemongo_bot/event_handlers/telegram_handler.py b/pokemongo_bot/event_handlers/telegram_handler.py index 8c3ab7d37c..7a42a12f47 100644 --- a/pokemongo_bot/event_handlers/telegram_handler.py +++ b/pokemongo_bot/event_handlers/telegram_handler.py @@ -11,32 +11,29 @@ from telegram.utils import request from chat_handler import ChatHandler -DEBUG_ON = False +DEBUG_ON = True class TelegramClass: update_id = None - def __init__(self, bot, master, pokemons, config): + def __init__(self, bot, pokemons, config): self.bot = bot request.CON_POOL_SIZE = 16 + self.config = config self.chat_handler = ChatHandler(self.bot, pokemons) + self.master = self.config.get('master') + with self.bot.database as conn: # initialize the DB table if it does not exist yet initiator = TelegramDBInit(bot.database) - - if master == None: # no master supplied - self.master = master - - # if master is not numeric, try to fetch it from the database - elif unicode(master).isnumeric(): # master is numeric - self.master = master - self.bot.logger.info("Telegram master is valid (numeric): {}".format(master)) - else: - self.bot.logger.info("Telegram master is not numeric: {}".format(master)) + if unicode(self.master).isnumeric(): # master is numeric + self.bot.logger.info("Telegram master is valid (numeric): {}".format(self.master)) + elif self.master is not None: # Master is not numeric, fetch from db + self.bot.logger.info("Telegram master is not numeric: {}".format(self.master)) c = conn.cursor() # do we already have a user id? - srchmaster = re.sub(r'^@', '', master) + srchmaster = re.sub(r'^@', '', self.master) c.execute("SELECT uid from telegram_uids where username in ('{}', '@{}')".format(srchmaster, srchmaster)) results = c.fetchall() if len(results) > 0: # woohoo, we already saw a message from this master and therefore have a uid @@ -44,13 +41,13 @@ def __init__(self, bot, master, pokemons, config): self.master = results[0][0] else: # uid not known yet self.bot.logger.info("Telegram master UID not in datastore yet") - self.master = master self.pokemons = pokemons self._tbot = None self.config = config def connect(self): + if DEBUG_ON: self.bot.logger.info("Not connected. Reconnecting") self._tbot = telegram.Bot(self.bot.config.telegram_token) try: self.update_id = self._tbot.getUpdates()[0].update_id @@ -61,6 +58,7 @@ def grab_uid(self, update): with self.bot.database as conn: conn.execute("replace into telegram_uids (uid, username) values (?, ?)", (update.message.chat_id, update.message.from_user.username)) conn.commit() + self.master = update.message.chat_id def isMasterFromConfigFile(self, chat_id): if not hasattr(self, "master") or not self.master: @@ -111,6 +109,7 @@ def authenticate(self, update): def run(self): time.sleep(1) while True: + if DEBUG_ON: self.bot.logger.info("Telegram loop running") if self._tbot is None: self.connect() @@ -167,6 +166,8 @@ def run(self): self.chat_handler.sendMessage(chat_id=update.message.chat_id, parse_mode='Markdown', text="Please /login first") continue # one way or another, the user is now authenticated + # make sure uid is in database + self.grab_uid(update) if update.message.text == "/info": self.chat_handler.send_player_stats_to_chat(update.message.chat_id) continue @@ -286,39 +287,15 @@ def __init__(self, bot, config): initiator = TelegramDBInit(bot.database) self.bot = bot self.tbot = None - master = config.get('master', None) self.pokemons = config.get('alert_catch', {}) self.whoami = "TelegramHandler" self.config = config self.chat_handler = ChatHandler(self.bot, self.pokemons) - - if master == None: - self.master = None - return - else: - self.master = master - - with self.bot.database as conn: - # if master is not numeric, try to fetch it from the database - if not unicode(master).isnumeric(): - self.bot.logger.info("Telegram master is not numeric: {}".format(master)) - c = conn.cursor() - # do we already have a user id? - srchmaster = re.sub(r'^@', '', master) - c.execute("SELECT uid from telegram_uids where username in ('{}', '@{}')".format(srchmaster, srchmaster)) - results = c.fetchall() - if len(results) > 0: # woohoo, we already saw a message from this master and therefore have a uid - self.bot.logger.info("Telegram master UID from datastore: {}".format(results[0][0])) - self.master = results[0][0] - else: # uid not known yet - self.bot.logger.info("Telegram master UID not in datastore yet") - self.master = master - self._connect() def _connect(self): self.bot.logger.info("Telegram bot not running. Starting") - self.tbot = TelegramClass(self.bot, self.master, self.pokemons, self.config) + self.tbot = TelegramClass(self.bot, self.pokemons, self.config) thread.start_new_thread(self.tbot.run) def catch_notify(self, pokemon, cp, iv, params): @@ -334,25 +311,30 @@ def catch_notify(self, pokemon, cp, iv, params): return False def handle_event(self, event, sender, level, formatted_msg, data): + #if DEBUG_ON: self.bot.logger.info("Handling an event {}".format(event)) + msg = None if self.tbot is None: if DEBUG_ON: self.bot.logger.info("handle_event Telegram bot not running.") try: self._connect() except Exception as inst: + self.bot.logger.error("Unable to start Telegram bot; exception: {}".format(pprint.pformat(inst))) self.tbot = None - self.bot.logger.error("Unable to start Telegram bot; master: {}, exception: {}".format(selfmaster, pprint.pformat(inst))) return msg = self.chat_handler.get_event(event, formatted_msg, data) - if msg is None: - return + + if not (self.tbot or msg): + return # first handle subscriptions; they are independent of master setting. with self.bot.database as conn: subs = conn.execute("select uid, parameters, event_type from telegram_subscriptions where event_type in (?,'all','debug')", [event]).fetchall() for sub in subs: + if DEBUG_ON: self.bot.logger.info("Processing sub {}".format(sub)) (uid, params, event_type) = sub if event != 'pokemon_caught' or self.catch_notify(data["pokemon"], int(data["cp"]), float(data["iv"]), params): + if DEBUG_ON: self.bot.logger.info("Matched sub {} event {}".format(sub, event)) if event == 'vanish_log' \ or event == 'eggs_hatched_log' \ or event == 'catch_log' \ @@ -368,17 +350,14 @@ def handle_event(self, event, sender, level, formatted_msg, data): pass elif event_type == "debug": self.bot.logger.info("[{}] {}".format(event, msg)) - else: msg = self.chat_handler.get_event(event, formatted_msg, data) - if msg is None: - return + + if DEBUG_ON: self.bot.logger.info("Telegram message {}".format(msg)) - if hasattr(self, "master") and self.master: - if not unicode(self.master).isnumeric(): - # master not numeric?... - # cannot send event notifications to non-numeric master (yet), so quitting - return - master = self.master - msg = self.chat_handler.get_event(event, formatted_msg, data) - self.chat_handler.sendMessage(chat_id=master, parse_mode='Markdown', text=msg) \ No newline at end of file + if msg is None: return + else: + if DEBUG_ON: self.bot.logger.info("No match sub {} event {}".format(sub, event)) + + if msg: + self.chat_handler.sendMessage(chat_id=uid, parse_mode='Markdown', text=msg) From f0921661dfc81297aedb9840bdf9711d05ecb751 Mon Sep 17 00:00:00 2001 From: Stuart Travers Date: Mon, 19 Sep 2016 11:07:08 +1000 Subject: [PATCH 3/5] Moved connect logic to after message building. No point calling the telegram handler at all if no msg to send (should be faster!) --- .../event_handlers/telegram_handler.py | 32 ++++++++----------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/pokemongo_bot/event_handlers/telegram_handler.py b/pokemongo_bot/event_handlers/telegram_handler.py index 7a42a12f47..ed6594187d 100644 --- a/pokemongo_bot/event_handlers/telegram_handler.py +++ b/pokemongo_bot/event_handlers/telegram_handler.py @@ -11,7 +11,7 @@ from telegram.utils import request from chat_handler import ChatHandler -DEBUG_ON = True +DEBUG_ON = False class TelegramClass: @@ -311,22 +311,7 @@ def catch_notify(self, pokemon, cp, iv, params): return False def handle_event(self, event, sender, level, formatted_msg, data): - #if DEBUG_ON: self.bot.logger.info("Handling an event {}".format(event)) msg = None - if self.tbot is None: - if DEBUG_ON: - self.bot.logger.info("handle_event Telegram bot not running.") - try: - self._connect() - except Exception as inst: - self.bot.logger.error("Unable to start Telegram bot; exception: {}".format(pprint.pformat(inst))) - self.tbot = None - return - msg = self.chat_handler.get_event(event, formatted_msg, data) - - if not (self.tbot or msg): - return - # first handle subscriptions; they are independent of master setting. with self.bot.database as conn: subs = conn.execute("select uid, parameters, event_type from telegram_subscriptions where event_type in (?,'all','debug')", [event]).fetchall() @@ -359,5 +344,16 @@ def handle_event(self, event, sender, level, formatted_msg, data): else: if DEBUG_ON: self.bot.logger.info("No match sub {} event {}".format(sub, event)) - if msg: - self.chat_handler.sendMessage(chat_id=uid, parse_mode='Markdown', text=msg) + if msg is not None: + if self.tbot is None: # instantiate tbot (TelegramClass) if not already set + if DEBUG_ON: + self.bot.logger.info("handle_event Telegram bot not running.") + try: + self._connect() + except Exception as inst: + self.bot.logger.error("Unable to start Telegram bot; exception: {}".format(pprint.pformat(inst))) + self.tbot = None + return + + if self.tbot is not None: # tbot should be running, but just in case it hasn't started yet + self.chat_handler.sendMessage(chat_id=uid, parse_mode='Markdown', text=msg) From 0cc5b28973fad1af0b035435e2c11628e7bc404a Mon Sep 17 00:00:00 2001 From: Stuart Travers Date: Mon, 19 Sep 2016 11:25:11 +1000 Subject: [PATCH 4/5] Sorted events Events return sorted alphabetically. Just makes things easier to read/find and tends to group like events together. --- pokemongo_bot/event_handlers/chat_handler.py | 1 + pokemongo_bot/event_handlers/telegram_handler.py | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pokemongo_bot/event_handlers/chat_handler.py b/pokemongo_bot/event_handlers/chat_handler.py index d5b436dee3..623e5c85dd 100644 --- a/pokemongo_bot/event_handlers/chat_handler.py +++ b/pokemongo_bot/event_handlers/chat_handler.py @@ -91,6 +91,7 @@ def get_events(self, update): events.remove('evolve_log') events.remove('transfer_log') events.remove('catchable_pokemon') + events = sorted(events) return events diff --git a/pokemongo_bot/event_handlers/telegram_handler.py b/pokemongo_bot/event_handlers/telegram_handler.py index ed6594187d..9ccfe9c734 100644 --- a/pokemongo_bot/event_handlers/telegram_handler.py +++ b/pokemongo_bot/event_handlers/telegram_handler.py @@ -32,9 +32,8 @@ def __init__(self, bot, pokemons, config): elif self.master is not None: # Master is not numeric, fetch from db self.bot.logger.info("Telegram master is not numeric: {}".format(self.master)) c = conn.cursor() - # do we already have a user id? srchmaster = re.sub(r'^@', '', self.master) - c.execute("SELECT uid from telegram_uids where username in ('{}', '@{}')".format(srchmaster, srchmaster)) + c.execute("SELECT uid from telegram_uids where username = '{}'".format(srchmaster)) results = c.fetchall() if len(results) > 0: # woohoo, we already saw a message from this master and therefore have a uid self.bot.logger.info("Telegram master UID from datastore: {}".format(results[0][0])) @@ -230,6 +229,7 @@ def showsubs(self, chatid): with self.bot.database as conn: for sub in conn.execute("select uid, event_type, parameters from telegram_subscriptions where uid = ?", [chatid]).fetchall(): subs.append("{} -> {}".format(sub[1], sub[2])) + if subs == []: subs.append("No subscriptions found. Subscribe using /sub EVENTNAME. For a list of events, send /events") self.chat_handler.sendMessage(chat_id=chatid, parse_mode='HTML', text="\n".join(subs)) def chsub(self, msg, chatid): From ff52eeec1a127851f42e840e6ef5c858a024d473 Mon Sep 17 00:00:00 2001 From: Stuart Travers Date: Mon, 19 Sep 2016 11:30:33 +1000 Subject: [PATCH 5/5] Removed unnecessary import (inventory) This has been moved to chathandler, so not needed in telegramhandler. All other imports required/in use. --- pokemongo_bot/event_handlers/telegram_handler.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pokemongo_bot/event_handlers/telegram_handler.py b/pokemongo_bot/event_handlers/telegram_handler.py index 9ccfe9c734..6f6cce74ff 100644 --- a/pokemongo_bot/event_handlers/telegram_handler.py +++ b/pokemongo_bot/event_handlers/telegram_handler.py @@ -7,7 +7,6 @@ import re import pprint from pokemongo_bot.datastore import Datastore -from pokemongo_bot import inventory from telegram.utils import request from chat_handler import ChatHandler