import logging import json from telegram.ext import Updater, CommandHandler, InlineQueryHandler, CallbackQueryHandler, MessageHandler, Filters from telegram import InlineQueryResultArticle, InputTextMessageContent, InlineKeyboardButton, InlineKeyboardMarkup #logging.basicConfig(level=logging.DEBUG, # format='%(asctime)s - %(name)s - %(levelname)s - %(message)s') names = {} with open('data/names.json') as file: names = json.load(file) namesToSearch = names.keys() oracleData = {} with open('data/oracle.json') as file: oracleData = json.load(file) print('Registered {} card names and {} oracle entries'.format(len(namesToSearch), len(oracleData))) crData = {} with open('data/cr.json') as file: crData = json.load(file) crDataNames = crData['glossary'].keys() crDataNumbers = crData['sections'].keys() print('Registered {} CR glossary terms and {} CR sections'.format(len(crDataNames), len(crDataNumbers))) def format_card(card): mana = '' if 'manaCost' in card: mana = '\t' + card['manaCost'] text = '' if 'text' in card: text = '\n' + card['text'] footer = '' if "Creature" in card['type']: footer = '\n{}/{}'.format(card['power'], card['toughness']) if "Planeswalker" in card['type'] and 'loyalty' in card: footer = '\n{}'.format(card['loyalty']) return '{}{}\n{}{}{}'.format( card['name'], mana, card['type'], text, footer) def preview_card(card): mana = '' if 'manaCost' in card: mana = '\t' + card['manaCost'] return '{}{}\n{}'.format( card['name'], mana, card['type']) def start(bot, update): commands = [ '/o - oracle text for a card', '/q - oracle text for cards mentioned in the question', '/cr
(coming soon)', '/ipg
(coming soon)', '/mtr
(coming soon)', ] update.message.reply_text('How can I help?\n{}'.format('\n'.join(commands)), quote = False) def search_names(words): nameCandidates = [name for name in namesToSearch if all(word in name.casefold() for word in words)] term = ' '.join(words) if len(words) > 1: goodCandidates = [name for name in nameCandidates if term in name.casefold()] if goodCandidates: nameCandidates = goodCandidates bestCandidates = [name for name in nameCandidates if term == name.casefold()] if bestCandidates: return bestCandidates return nameCandidates def oracle(bot, update, args): if not args: update.message.reply_text('I need some clues to search for, my master!', quote=False) return words = [word.casefold() for word in args] nameCandidates = search_names(words) if not nameCandidates: update.message.reply_text('I searched very thoroughly, but returned empty-handed, my master!', quote=False) return if len(nameCandidates) > 20: update.message.reply_text('I need more specific clues, my master! This would return {} names'.format(len(nameCandidates)), quote=False) return if len(nameCandidates) > 1: reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton(name, callback_data=name)] for name in nameCandidates]) update.message.reply_text('Which one?', reply_markup=reply_markup, quote=False) return reply = [] for name in nameCandidates: for uniqueName in names[name]: reply.append(format_card(oracleData[uniqueName])) update.message.reply_text('\n'.join(reply), parse_mode='HTML', quote = False) def question(bot, update, args): text = ' '.join(args).casefold() reply = [] for name in namesToSearch: if name.casefold() in text: reply.append('"' + name + '":\n' + '\n'.join([format_card(oracleData[uniqueName]) for uniqueName in names[name]])) if reply: update.message.reply_text('\n\n'.join(reply), parse_mode='HTML', quote = False) def inline_oracle(bot, update): query = update.inline_query.query.casefold() if not query: return if len(query) < 3: return words = query.split() nameCandidates = search_names(words) if not nameCandidates: return results = list() for word in nameCandidates[:3]: for uniqueName in names[word]: results.append( InlineQueryResultArticle( id=oracleData[uniqueName]['name'], title=word, description=preview_card(oracleData[uniqueName]), input_message_content=InputTextMessageContent(format_card(oracleData[uniqueName]), parse_mode='HTML') ) ) bot.answerInlineQuery(update.inline_query.id, results) def callback_name(bot, update): message_id = update.callback_query.message.message_id chat_id = update.callback_query.message.chat.id name = update.callback_query.data if not name in oracleData: return bot.editMessageText( chat_id = chat_id, message_id = message_id, parse_mode = 'HTML', text = '\n'.join([format_card(oracleData[uniqueName]) for uniqueName in names[name]]) ) bot.answerCallbackQuery(update.callback_query.id) def text(bot, update): if update.message.chat.type != 'private': return text = update.message.text if len(text) < 30: oracle(bot, update, text.split()) else: question(bot, update, text) def comp_rules(bot, update, args): if not args: update.message.reply_text('I need some clues to search for, my master!', quote=False) return words = [word.casefold() for word in args] if words[0][0].isdigit(): lang = 'en' if len(words) > 1 and words[1] == 'ru': lang = 'ru' results = [] other = [] section = words[0].casefold() pos = len(section) for name in sorted([name for name in crDataNumbers if name.startswith(section)]): diff = name[pos:].strip('.') if len(diff) < 2 and (len(diff) == 0 or diff.isalpha()): results.append(name) elif not diff[-1:].isalpha(): other.append(name) text = '\n'.join(['{} {}'.format(name, crData['sections'][name][lang]) for name in results]) if other: text += '\n(Subsections: {}-{})'.format(other[0], other[-1]) if len(text) > 4000: text = '{} {}\n(See also: {}-{})'.format(results[0], crData['sections'][results[0]][lang], results[1], results[-1]) update.message.reply_text(text, parse_mode='HTML', quote = False) return nameCandidates = [name for name in crDataNames if all(word in name.casefold() for word in words)] term = ' '.join(words) if len(words) > 1: goodCandidates = [name for name in nameCandidates if term in name.casefold()] if goodCandidates: nameCandidates = goodCandidates bestCandidates = [name for name in nameCandidates if name.casefold().startswith(term)] if bestCandidates: nameCandidates = bestCandidates excellentCandidate = [name for name in nameCandidates if name.casefold() == term] if excellentCandidate: nameCandidates = excellentCandidate if not nameCandidates: update.message.reply_text('I searched very thoroughly, but returned empty-handed, my master!', quote=False) return if len(nameCandidates) > 20: update.message.reply_text('I need more specific clues, my master! This would return {} names'.format(len(nameCandidates)), quote=False) return text = '\n'.join(['{} {}'.format(name, crData['glossary'][name]) for name in sorted(nameCandidates)]) update.message.reply_text(text, parse_mode='HTML', quote = False) def dispatcher_setup(dispatcher): dispatcher.add_handler(CommandHandler('start', start)) dispatcher.add_handler(CommandHandler('help', start)) dispatcher.add_handler(CommandHandler('o', oracle, pass_args=True)) dispatcher.add_handler(CommandHandler('q', question, pass_args=True)) dispatcher.add_handler(CommandHandler('cr', comp_rules, pass_args=True)) dispatcher.add_handler(InlineQueryHandler(inline_oracle)) dispatcher.add_handler(CallbackQueryHandler(callback_name)) dispatcher.add_handler(MessageHandler(Filters.text, text)) with open('token') as file: token = file.read().strip() updater = Updater(token) dispatcher_setup(updater.dispatcher) updater.start_polling() updater.idle()