216 lines
7.5 KiB
Python
216 lines
7.5 KiB
Python
import sys
|
|
import time
|
|
import telepot
|
|
from pprint import pprint
|
|
from telepot.namedtuple import InlineKeyboardMarkup, InlineKeyboardButton
|
|
|
|
import config
|
|
import commands
|
|
import db
|
|
|
|
class CallbackRequest():
|
|
def __init__(self, callback, argname, kwargs):
|
|
self.callback = callback
|
|
self.argname = argname
|
|
self.kwargs = kwargs
|
|
|
|
class MessageHandler(telepot.helper.ChatHandler):
|
|
def __init__(self, *args, **kwargs):
|
|
super(MessageHandler, self).__init__(*args, **kwargs)
|
|
self.sender_id = None
|
|
self.username = None
|
|
self.is_group = None
|
|
self.groupname = None
|
|
self.command = None
|
|
self.args = None
|
|
self.message = None
|
|
self.player = None # not automatically initialized
|
|
self.group = None # not automatically initialized
|
|
self.callback = None # string to be read requested
|
|
|
|
def on_chat_message(self, msg):
|
|
"""
|
|
Process received messages.
|
|
|
|
msg -- The received message
|
|
"""
|
|
if 'text' not in msg:
|
|
# probably a sticker or something
|
|
return
|
|
|
|
if self.callback and self.sender_id != msg['from']['id']:
|
|
# once in callback mode, ignore everyone else
|
|
return
|
|
|
|
text = msg['text']
|
|
#self.chat_id = msg['chat']['id']
|
|
self.sender_id = msg['from']['id']
|
|
self.username = get_value_from(msg['from'], ['username', 'first_name', 'id'], 'unknown-user-id')
|
|
self.is_group = msg['chat']['type'] == 'group'
|
|
self.groupname = msg['chat']['title'] if 'title' in msg['chat'] else None
|
|
#log('chat id {} from {}: {}'.format(self.chat_id, self.sender_id, str(msg)))
|
|
|
|
if self.callback:
|
|
log_msg(msg)
|
|
callback = self.callback
|
|
self.callback = None
|
|
callback.kwargs[callback.argname] = text
|
|
self.dbc = db.open_connection()
|
|
callback.callback(self, **callback.kwargs)
|
|
db.close_connection(self.dbc)
|
|
return
|
|
|
|
# avoid logging and processing every single message.
|
|
if text[0] != '/':
|
|
return
|
|
# get command, ignore bot username
|
|
self.args=text.split()
|
|
command = self.args[0]
|
|
if '@' in command:
|
|
more_split = command.split('@', maxsplit=1)
|
|
command = more_split[0]
|
|
# skip '/'
|
|
self.command = command[1:]
|
|
|
|
log_msg(msg)
|
|
|
|
#is_admin = False
|
|
#if sender_id in config.admins:
|
|
# is_admin = True
|
|
|
|
if self.command in commands.all_commands:
|
|
self.dbc = db.open_connection()
|
|
commands.all_commands[self.command](self)
|
|
db.close_connection(self.dbc)
|
|
|
|
def read_answer(self, callback, argname, kwargs):
|
|
self.callback = CallbackRequest(callback, argname, kwargs)
|
|
|
|
def burn_message(self, msg_id):
|
|
# destroy the inline keyboard
|
|
#self.bot.deleteMessage((self.chat_id, msg['message']['message_id']))
|
|
self.bot.editMessageText(msg_id, 'Too late.')
|
|
pass
|
|
|
|
def send(self, msg, target=None, disablepreview=True, options={}, allowedit=False):
|
|
if (msg == None or len(msg) == 0 or len(msg.split()) == 0) and len(options) == 0:
|
|
msg = '(no message)'
|
|
|
|
keyboard = None
|
|
if len(options) > 0:
|
|
buttons = []
|
|
for key, value in options.items():
|
|
if isinstance(value, dict):
|
|
if 'url' in value:
|
|
buttons.append([InlineKeyboardButton(text=key, url=value['url'])])
|
|
else:
|
|
sublist = []
|
|
for key, subvalue in value.items():
|
|
if isinstance(subvalue, dict) and 'url' in subvalue:
|
|
sublist.append(InlineKeyboardButton(text=key, url=subvalue['url']))
|
|
else:
|
|
sublist.append(InlineKeyboardButton(text=key, callback_data=subvalue))
|
|
buttons.append(sublist)
|
|
else:
|
|
buttons.append([InlineKeyboardButton(text=key, callback_data=value)])
|
|
keyboard = InlineKeyboardMarkup(inline_keyboard=buttons)
|
|
|
|
#log('sending to chat id {}'.format(target))
|
|
if target is None:
|
|
if self.message is not None:
|
|
self.bot.deleteMessage(self.message)
|
|
self.message = None
|
|
sent = self.bot.sendMessage(self.chat_id, msg, disable_web_page_preview=disablepreview, reply_markup=keyboard)
|
|
if allowedit:
|
|
self.message = telepot.message_identifier(sent)
|
|
else:
|
|
self.message = None
|
|
else:
|
|
self.bot.sendMessage(target, msg, disable_web_page_preview=disablepreview, reply_markup=keyboard)
|
|
|
|
def delete(self):
|
|
self.bot.deleteMessage(self.message)
|
|
self.message = None
|
|
|
|
def on_callback_query(self, msg):
|
|
query_id, from_id, query_data = telepot.glance(msg, flavor='callback_query')
|
|
#self.bot.sendMessage(from_id, str(msg))
|
|
#log('callback chat id {} from {}: {}'.format(self.chat_id, from_id, str(msg)))
|
|
|
|
if self.callback and self.sender_id != from_id:
|
|
# once in callback mode, ignore everyone else
|
|
return
|
|
|
|
if self.message is None:
|
|
# probably bot restarted
|
|
self.message = (self.chat_id, msg['message']['message_id'])
|
|
|
|
log_callback(msg, self.callback)
|
|
|
|
if self.callback:
|
|
callback = self.callback
|
|
self.callback = None
|
|
callback.kwargs[callback.argname] = query_data
|
|
self.dbc = db.open_connection()
|
|
callback.callback(self, **callback.kwargs)
|
|
db.close_connection(self.dbc)
|
|
return
|
|
if query_data in commands.all_commands:
|
|
self.command = query_data
|
|
self.dbc = db.open_connection()
|
|
commands.all_commands[query_data](self)
|
|
db.close_connection(self.dbc)
|
|
return
|
|
#bot.answerCallbackQuery(query_id) #, text='Got it')
|
|
# Destroy message if we can't understand what it is. Probably an old message.
|
|
self.burn_message(self.message)
|
|
|
|
def on_close(self, ex):
|
|
try:
|
|
self.burn_message(self.message)
|
|
except:
|
|
pass
|
|
|
|
def die():
|
|
os.kill(os.getpid(), signal.SIGINT)
|
|
|
|
def fatal(msg):
|
|
print(msg)
|
|
die()
|
|
|
|
def log(msg):
|
|
f = open(config.log_file, 'a')
|
|
f.write(msg + "\n")
|
|
f.close()
|
|
print(msg)
|
|
|
|
def log_callback(msg, callback):
|
|
query_id, from_id, query_data = telepot.glance(msg, flavor='callback_query')
|
|
chat_name = ''
|
|
username = get_value_from(msg['from'], ['username', 'first_name', 'id'], 'unknown-user-id')
|
|
log('{}: callback {}: {}'.format(username, callback.argname if callback is not None else '(none)', query_data))
|
|
|
|
def log_msg(msg):
|
|
chat_name = ''
|
|
username = ''
|
|
username = get_value_from(msg['from'], ['username', 'first_name'], 'unknown-user-id')
|
|
username = '{}[{}]'.format(username, msg['from']['id'])
|
|
text = msg['text']
|
|
if 'title' in msg['chat']:
|
|
chat_name = '{} ({})'.format(msg['chat']['title'], username)
|
|
else:
|
|
chat_name = username
|
|
log('{}: {}'.format(chat_name, text))
|
|
|
|
def get_value_from(entry, value, default):
|
|
if isinstance(value, list):
|
|
for attempt in value:
|
|
if attempt in entry:
|
|
return entry[attempt]
|
|
elif isinstance(value, str):
|
|
if value in entry:
|
|
return entry[value]
|
|
return default
|
|
|
|
|