Skip to content

Commit

Permalink
Merge pull request #4951 from askovpen/dev
Browse files Browse the repository at this point in the history
Telegram to thread
  • Loading branch information
solderzzc authored Aug 30, 2016
2 parents 8c74150 + 09a0290 commit 1d39d9a
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 108 deletions.
1 change: 0 additions & 1 deletion configs/config.json.example
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
"config": {
"enabled": false,
"master": null,
"min_interval": 120,
"// old syntax, still supported: alert_catch": ["all"],
"// new syntax:": {},
"alert_catch": {
Expand Down
2 changes: 0 additions & 2 deletions docs/configuration_files.md
Original file line number Diff line number Diff line change
Expand Up @@ -991,7 +991,6 @@ Bot answer on command '/info' self stats.
* `telegram_token` : bot token (getting [there](https://core.telegram.org/bots#6-botfather) - one token per bot)
* `master` : id (without quotes) of bot owner, who will gett announces.
* `alert_catch` : dict of rules pokemons catch.
* `min_interval`: min interval check messages from telegram.

### Sample configuration
[[back to top](#table-of-contents)]
Expand All @@ -1001,7 +1000,6 @@ Bot answer on command '/info' self stats.
"config": {
"enabled": true,
"master": 12345678,
"min_interval": 120,
"alert_catch": {
"all": {"operator": "and", "cp": 1300, "iv": 0.95},
"Snorlax": {"operator": "or", "cp": 900, "iv": 0.9}
Expand Down
100 changes: 2 additions & 98 deletions pokemongo_bot/cell_workers/telegram_task.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -14,108 +14,12 @@ class FileIOException(Exception):

class TelegramTask(BaseTask):
SUPPORTED_TASK_API_VERSION = 1
update_id = None
tbot = None
min_interval = None
next_job = None

def initialize(self):
if not self.enabled:
return
api_key = self.bot.config.telegram_token
if api_key is None:
self.emit_event(
'config_error',
formatted='api_key not defined.'
)
return
self.tbot = telegram.Bot(api_key)
self.master = self.config.get('master', None)
if self.master:
self.bot.event_manager.add_handler(TelegramHandler(self.tbot, self.master, self.config.get('alert_catch')))
try:
self.update_id = self.tbot.getUpdates()[0].update_id
except IndexError:
self.update_id = None
self.min_interval = self.config.get('min_interval', 120)
self.next_job = datetime.now() + timedelta(seconds=self.min_interval)
self.bot.event_manager.add_handler(TelegramHandler(self.bot, self.config))

def work(self):
if not self.enabled:
return
if datetime.now() < self.next_job:
return
self.next_job = datetime.now() + timedelta(seconds=self.min_interval)
for update in self.tbot.getUpdates(offset=self.update_id, timeout=10):
self.update_id = update.update_id+1
if update.message:
self.bot.logger.info("message from {} ({}): {}".format(update.message.from_user.username, update.message.from_user.id, update.message.text))
if self.config.get('master', None) and self.config.get('master', None) not in [update.message.from_user.id, "@{}".format(update.message.from_user.username)]:
self.emit_event(
'debug',
formatted="Master wrong: expecting {}, got {}({})".format(self.master, update.message.from_user.username, update.message.from_user.id))
continue
else:
if not re.match(r'^[0-9]+$', "{}".format(self.config['master'])): # master was not numeric...
self.config['master'] = update.message.chat_id
idx = (i for i,v in enumerate(self.bot.event_manager._handlers) if type(v) is TelegramHandler).next()
self.bot.event_manager._handlers[idx] = TelegramHandler(self.tbot, self.master, self.config.get('alert_catch'))
if update.message.text == "/info":
stats = self._get_player_stats()
if stats:
with self.bot.database as conn:
cur = conn.cursor()
cur.execute("SELECT DISTINCT COUNT(encounter_id) FROM catch_log WHERE dated >= datetime('now','-1 day')")
catch_day = cur.fetchone()[0]
cur.execute("SELECT DISTINCT COUNT(pokestop) FROM pokestop_log WHERE dated >= datetime('now','-1 day')")
ps_day = cur.fetchone()[0]
res = (
"*"+self.bot.config.username+"*",
"_Level:_ "+str(stats["level"]),
"_XP:_ "+str(stats["experience"])+"/"+str(stats["next_level_xp"]),
"_Pokemons Captured:_ "+str(stats["pokemons_captured"])+" ("+str(catch_day)+" _last 24h_)",
"_Poke Stop Visits:_ "+str(stats["poke_stop_visits"])+" ("+str(ps_day)+" _last 24h_)",
"_KM Walked:_ "+str(stats["km_walked"])
)
self.send_message(chat_id=update.message.chat_id, parse_mode='Markdown', text="\n".join(res))
self.send_location(chat_id=update.message.chat_id, latitude=self.bot.api._position_lat, longitude=self.bot.api._position_lng)
else:
self.send_message(chat_id=update.message.chat_id, parse_mode='Markdown', text="Stats not loaded yet\n")
elif update.message.text == "/start" or update.message.text == "/help":
res = (
"Commands: ",
"/info - info about bot"
)
self.send_message(chat_id=update.message.chat_id, parse_mode='Markdown', text="\n".join(res))
def send_message(self, chat_id, parse_mode, text):
try:
self.tbot.sendMessage(chat_id, parse_mode, text)
except telegram.error.NetworkError:
pass
def send_location(self, chat_id, latitude, longitude):
try:
self.tbot.send_location(chat_id, latitude, longitude)
except telegram.error.NetworkError:
pass
def _get_player_stats(self):
"""
Helper method parsing the bot inventory object and returning the player stats object.
:return: The player stats object.
:rtype: dict
"""
web_inventory = os.path.join(_base_dir, "web", "inventory-%s.json" % self.bot.config.username)

try:
with open(web_inventory, "r") as infile:
json_inventory = json.load(infile)
except ValueError as exception:
# Unable to read json from web inventory
# File may be corrupt. Create a new one.
self.bot.logger.info('[x] Error while opening inventory file for read: %s' % exception)
json_inventory = []
except:
raise FileIOException("Unexpected error reading from {}".format(web_inventory))

return next((x["inventory_item_data"]["player_stats"]
for x in json_inventory
if x.get("inventory_item_data", {}).get("player_stats", {})),
None)
107 changes: 100 additions & 7 deletions pokemongo_bot/event_handlers/telegram_handler.py
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,18 +1,111 @@
# -*- coding: utf-8 -*-
from pokemongo_bot.event_manager import EventHandler
from pokemongo_bot.base_dir import _base_dir
import json
import os
import time
import telegram
import thread
import re

DEBUG_ON = False

class FileIOException(Exception):
pass

class TelegramClass:

update_id = None

def __init__(self, bot, master, pokemons):
self.bot = bot
self.master = master
self.pokemons = pokemons
self._tbot = None

def sendMessage(self, chat_id=None, parse_mode='Markdown', text=None):
self._tbot.sendMessage(chat_id=chat_id, parse_mode=parse_mode, text=text)

def connect(self):
self._tbot = telegram.Bot(self.bot.config.telegram_token)
try:
self.update_id = self._tbot.getUpdates()[0].update_id
except IndexError:
self.update_id = None

def _get_player_stats(self):
web_inventory = os.path.join(_base_dir, "web", "inventory-%s.json" % self.bot.config.username)
try:
with open(web_inventory, "r") as infile:
json_inventory = json.load(infile)
except ValueError as exception:
self.bot.logger.info('[x] Error while opening inventory file for read: %s' % exception)
json_inventory = []
except:
raise FileIOException("Unexpected error reading from {}".format(web_inventory))
return next((x["inventory_item_data"]["player_stats"]
for x in json_inventory
if x.get("inventory_item_data", {}).get("player_stats", {})),
None)

def run(self):
time.sleep(1)
while True:
try:
for update in self._tbot.getUpdates(offset=self.update_id, timeout=10):
self.update_id = update.update_id+1
if update.message:
self.bot.logger.info("message from {} ({}): {}".format(update.message.from_user.username, update.message.from_user.id, update.message.text))
if self.master and self.master not in [update.message.from_user.id, "@{}".format(update.message.from_user.username)]:
continue
if update.message.text == "/info":
stats = self._get_player_stats()
if stats:
with self.bot.database as conn:
cur = conn.cursor()
cur.execute("SELECT DISTINCT COUNT(encounter_id) FROM catch_log WHERE dated >= datetime('now','-1 day')")
catch_day = cur.fetchone()[0]
cur.execute("SELECT DISTINCT COUNT(pokestop) FROM pokestop_log WHERE dated >= datetime('now','-1 day')")
ps_day = cur.fetchone()[0]
res = (
"*"+self.bot.config.username+"*",
"_Level:_ "+str(stats["level"]),
"_XP:_ "+str(stats["experience"])+"/"+str(stats["next_level_xp"]),
"_Pokemons Captured:_ "+str(stats["pokemons_captured"])+" ("+str(catch_day)+" _last 24h_)",
"_Poke Stop Visits:_ "+str(stats["poke_stop_visits"])+" ("+str(ps_day)+" _last 24h_)",
"_KM Walked:_ "+str(stats["km_walked"])
)
self._tbot.sendMessage(chat_id=update.message.chat_id, parse_mode='Markdown', text="\n".join(res))
self._tbot.send_location(chat_id=update.message.chat_id, latitude=self.bot.api._position_lat, longitude=self.bot.api._position_lng)
else:
self._tbot.sendMessage(chat_id=update.message.chat_id, parse_mode='Markdown', text="Stats not loaded yet\n")
elif update.message.text == "/start" or update.message.text == "/help":
res = (
"Commands: ",
"/info - info about bot"
)
self._tbot.sendMessage(chat_id=update.message.chat_id, parse_mode='Markdown', text="\n".join(res))
except telegram.error.NetworkError:
time.sleep(1)
except telegram.error.Unauthorized:
self.update_id += 1

class TelegramHandler(EventHandler):
def __init__(self, tbot,master,pokemons):
self.tbot = tbot
self.master=master
self.pokemons=pokemons
self.whoami="TelegramHandler"
def __init__(self, bot, config):
self.bot = bot
self.tbot = None
self.master = config.get('master', None)
self.pokemons = config.get('alert_catch', {})
self.whoami = "TelegramHandler"

def handle_event(self, event, sender, level, formatted_msg, data):
if self.tbot is None:
try:
self.tbot = TelegramClass(self.bot, self.master, self.pokemons)
self.tbot.connect()
thread.start_new_thread(self.tbot.run)
except Exception as inst:
self.tbot = None
if self.master:
if not re.match(r'^[0-9]+$', str(self.master)):
return
Expand All @@ -23,7 +116,7 @@ def handle_event(self, event, sender, level, formatted_msg, data):
elif event == 'pokemon_caught':
if isinstance(self.pokemons, list):
if data["pokemon"] in self.pokemons or "all" in self.pokemons:
msg = "Caught {} CP: {}, IV: {}".format(data["pokemon"],data["cp"],data["iv"])
msg = "Caught {} CP: {}, IV: {}".format(data["pokemon"], data["cp"], data["iv"])
else:
return
else:
Expand All @@ -34,7 +127,7 @@ def handle_event(self, event, sender, level, formatted_msg, data):
else:
return
if (not "operator" in trigger or trigger["operator"] == "and") and data["cp"] >= trigger["cp"] and data["iv"] >= trigger["iv"] or ("operator" in trigger and trigger["operator"] == "or" and (data["cp"] >= trigger["cp"] or data["iv"] >= trigger["iv"])):
msg = "Caught {} CP: {}, IV: {}".format(data["pokemon"],data["cp"],data["iv"])
msg = "Caught {} CP: {}, IV: {}".format(data["pokemon"], data["cp"], data["iv"])
else:
return
else:
Expand Down

0 comments on commit 1d39d9a

Please sign in to comment.