def command_map(update, context): code = None if len(context.args) > 0: resolved = resolve_query_string(context.args[0]) if resolved: code = resolved photo = wikidata.cases_country_map(code) elif WORLD_IDENT in context.args[0]: code = WORLD_IDENT photo = wikidata.cases_world_map() else: update.message.reply_text(resolve('unknown_place', lang(update))) return else: if 'country' in context.chat_data: code = context.chat_data['country'] photo = wikidata.cases_country_map(code) else: code = WORLD_IDENT photo = wikidata.cases_world_map() if photo: caption = resolve("map_caption", lang(update), *get_name_and_icon(code)) update.message.reply_photo(photo=photo, caption=caption, parse_mode=ParseMode.MARKDOWN) else: update.message.reply_text(resolve('unknown_place', lang(update)))
def get_list_keyboard(update, current_index, limit, last=False): keyboard = [[]] if current_index > 0: keyboard[0].append( InlineKeyboardButton(resolve('page_left', lang(update), current_index), callback_data="list {} {}".format( current_index - 1, limit))) if not last: keyboard[0].append( InlineKeyboardButton(resolve('page_right', lang(update), current_index + 2), callback_data="list {} {}".format( current_index + 1, limit))) if current_index > 0: keyboard.append([ InlineKeyboardButton(resolve('to_start', lang(update)), callback_data="list 0 {}".format(limit)) ]) else: keyboard.append([ InlineKeyboardButton(resolve('to_end', lang(update)), callback_data="list -1 {}".format(limit)) ]) keyboard.append([ InlineKeyboardButton( resolve('sort_order', lang(update)), callback_data="list_order_menu 1 ({} {} {})".format( current_index, limit, int(last))) ]) return InlineKeyboardMarkup(keyboard)
def callback_list_pages(update, context): query = update.callback_query order = context.chat_data.get('order', SORT_ORDERS[0]) # for backward comp page, limit = int(context.match.group(1)), int(context.match.group(2)) if order in ["vaccinations"]: case_list = api.vaccinations_country_list(sort_by=order) else: case_list = api.cases_country_list(sort_by=order) if page >= 0: case_list = case_list[page*limit:(page+1)*limit] else: # if the given page number is negative, we want to access the last page page = len(case_list) // limit offset = len(case_list) % limit case_list = case_list[-offset:] query.answer() if len(case_list) > 0: text = resolve('list_header', lang(update), resolve("sort_order_"+order, lang(update))) for item in case_list: text += format_list_item(item, order) query.edit_message_text(text=text, parse_mode=ParseMode.MARKDOWN, reply_markup=get_list_keyboard(update, page, limit, len(case_list) < limit)) else: query.edit_message_text(resolve('no_data', lang(update)), reply_markup=get_list_keyboard(update, page, limit, len(case_list) < limit))
def format_stats(update, code, data, icon=None, detailed=False): if code in api.countries: name = api.countries[code]['name'] elif code == WORLD_IDENT: name = "the World" icon = '\U0001f310' else: name = code if not icon: icon = flag(code) p_dead = data['deaths'] / data['cases'] if 'active' in data and 'todayCases' in data: # we have detailed data, so use more detailed view p_active = data['active'] / data['cases'] p_recov = data['recovered'] / data['cases'] text = resolve('stats_table', lang(update), name, icon, data['cases'], data['active'], p_active, data['recovered'], p_recov, data['deaths'], p_dead, data['todayCases'], data['todayDeaths']) if detailed: text += '\n' + resolve('stats_table_more', lang(update), data['casesPerOneMillion'] or 0, data['deathsPerOneMillion'] or 0) else: # we only have limited data text = resolve('stats_table_simple', lang(update), name, icon, data['cases'], data['deaths'], p_dead) text += '\n' + resolve('stats_updated', lang(update), datetime.utcfromtimestamp(data['updated'] / 1e3)) return text
def command_list(update, context): # set or retrieve sort order if len(context.args) > 0: order = context.args[0] context.chat_data['order'] = order elif 'order' in context.chat_data: order = context.chat_data['order'] else: # use first possible order as default order = SORT_ORDERS[0] context.chat_data['order'] = order # by default, return 8 items. min 2 and max 20. limit = int(context.args[1]) if len(context.args) > 1 else 8 limit = min(max(2, limit), 20) if order in ["vaccinations"]: case_list = api.vaccinations_country_list(sort_by=order)[:limit] else: case_list = api.cases_country_list(sort_by=order)[:limit] if len(case_list) > 0: text = resolve('list_header', lang(update), resolve("sort_order_"+order, lang(update))) for item in case_list: text += format_list_item(item, order) update.message.reply_markdown(text, reply_markup=get_list_keyboard(update, 0, limit)) else: update.message.reply_text(resolve('no_data', lang(update)))
def get_stats_keyboard(update, country_code): keyboard = [] keyboard.append([ InlineKeyboardButton(resolve("stats_map", lang(update)), callback_data="map {}".format(country_code)) ]) keyboard.append([ InlineKeyboardButton(resolve("stats_graph_cases", lang(update)), callback_data="graph {}".format(country_code)), InlineKeyboardButton(resolve("stats_graph_vacc", lang(update)), callback_data="vacc {}".format(country_code)) ]) return InlineKeyboardMarkup(keyboard)
def handle_setcountry_input(update, context): query_string = update.message.text.lower() if query_string in api.name_map: code = api.name_map[query_string] context.chat_data['country'] = code update.message.reply_markdown( resolve('setcountry_success', lang(update), api.countries[code]['name'])) return ConversationHandler.END else: update.message.reply_text(resolve('unknown_place', lang(update)))
def get_list_order_keyboard(update, current_index, limit, last=False): keyboard = [] l = None for i, sort_order in enumerate(SORT_ORDERS): button = InlineKeyboardButton(resolve("sort_order_"+sort_order, lang(update)), callback_data="list_order {} {}".format(sort_order, limit)) if i % 2 == 0: if l: keyboard.append(l) l = [button] else: l.append(button) keyboard.append(l) keyboard.append([InlineKeyboardButton(resolve('back', lang(update)), callback_data="list_order_menu 0 ({} {} {})".format(current_index, limit, int(last)))]) return InlineKeyboardMarkup(keyboard)
def command_de_state(update, context, state): data = api.cases_de_state(state) if data: text = format_stats(update, state.title(), data, icon='\uD83C\uDDE9\uD83C\uDDEA') update.message.reply_markdown(text) else: update.message.reply_text(resolve('no_data', lang(update)))
def command_country(update, context, country_code): data = api.cases_country(country_code) if data: text = format_stats(update, country_code, data) update.message.reply_markdown(text, reply_markup=get_stats_keyboard(update, country_code)) else: update.message.reply_text(resolve('no_data', lang(update)))
def command_world(update, context): data = api.cases_world() if data: text = format_stats(update, WORLD_IDENT, data) update.message.reply_markdown(text, reply_markup=get_stats_keyboard(update, WORLD_IDENT)) else: update.message.reply_text(resolve('no_data', lang(update)))
def format_list_item(data, order): code = data['countryInfo']['iso2'].lower() icon = resolve('sort_order_'+order, None).split(' ')[0] number = data[order] text = """ {} *{} - {}* - {} `{:,}` """.format(flag(code), data['country'], '/'+code, icon, number) return text
def format_stats(update, code, data, icon=None, detailed=True): name, icon = get_name_and_icon(code, icon=icon) p_dead = data['deaths'] / data['cases'] if 'active' in data and 'todayCases' in data: # we have detailed data, so use more detailed view p_active = data['active'] / data['cases'] p_recov = data['recovered'] / data['cases'] text = resolve('stats_table', lang(update), name, icon, data['cases'], data['active'], p_active, data['recovered'], p_recov, data['deaths'], p_dead, data.get('vaccinations', math.nan), data['todayCases'], data['todayDeaths']) if detailed: text += '\n'+resolve('stats_table_more', lang(update), data['casesPerOneMillion'], data['deathsPerOneMillion'], data['testsPerOneMillion']) else: # we only have limited data text = resolve('stats_table_simple', lang(update), name, icon, data['cases'], data['deaths'], p_dead) text += '\n'+resolve('stats_updated', lang(update), datetime.utcfromtimestamp(data['updated'] / 1e3)) return text
def callback_map(update, context): code = context.match.group(1) if code == WORLD_IDENT: photo = wikidata.cases_world_map() else: photo = wikidata.cases_country_map(code) if photo: caption = resolve("map_caption", lang(update), *get_name_and_icon(code)) update.callback_query.answer() context.bot.send_photo( chat_id=update.callback_query.message.chat_id, photo=photo, caption=caption, parse_mode=ParseMode.MARKDOWN, ) else: update.callback_query.answer() context.bot.send_message(chat_id=update.callback_query.message.chat_id, text=resolve('no_data', lang(update)))
def get_stats_keyboard(update, country_code, is_detailed=False): keyboard = [[]] caption_key = 'stats_more' if not is_detailed else 'stats_less' caption = resolve(caption_key, lang(update)) keyboard[0].append( InlineKeyboardButton(caption, callback_data="stats {} {}".format( country_code, 1 if is_detailed else 0))) return InlineKeyboardMarkup(keyboard)
def handle_inlinequery(update, context): inline_query = update.inline_query query_string = inline_query.query.lower() if not query_string: return results = [] # a special case matching 'world' if WORLD_IDENT.startswith(query_string): results.append((WORLD_IDENT, WORLD_IDENT)) for name in api.name_map.keys(): if name.startswith(query_string): results.append((name, "country")) # limit to the first threee results if len(results) >= 3: break if len(results) < 3: for state in api.us_states: if state.lower().startswith(query_string): results.append((state.lower(), "us_state")) if len(results) >= 3: break if len(results) < 3: for state in api.de_states: if state.lower().startswith(query_string): results.append((state.lower(), "de_state")) if len(results) >= 3: break query_results = [] for i, (s, t) in enumerate(results): if t == WORLD_IDENT: data = api.cases_world() text = format_stats(update, WORLD_IDENT, data, detailed=True) elif t == "us_state": data = api.cases_us_state(s) text = format_stats(update, s.title(), data, icon='\uD83C\uDDFA\uD83C\uDDF8') elif t == "de_state": data = api.cases_de_state(s) text = format_stats(update, s.title(), data, icon='\uD83C\uDDE9\uD83C\uDDEA') else: country_code = api.name_map[s] data = api.cases_country(country_code) text = format_stats(update, country_code, data, detailed=True) text += '\n' + resolve('more', lang(update)) result_content = InputTextMessageContent(text, parse_mode=ParseMode.MARKDOWN) query_results.append( InlineQueryResultArticle(id=i, title=s, input_message_content=result_content)) inline_query.answer(query_results)
def get_status_report(country_code=None, lang="en"): data = api.cases_world() if data: dt = datetime.utcfromtimestamp(data['updated'] / 1e3) text = resolve('today', lang, dt, dt, data['cases'], data['deaths'], data['todayCases'], data['todayDeaths'], data['vaccinations']) # fetch data of home country if set if country_code: country_data = api.cases_country(country_code) text += '\n'+resolve('today_country', lang, flag(country_code), api.countries[country_code]['name'], country_data['cases'], country_data['deaths'], country_data['todayCases'], country_data['todayDeaths'], country_data.get('vaccinations', math.nan), country_code.lower() ) else: text += '\n_'+resolve('no_country_set', lang)+'_\n' text += '\n'+resolve('today_footer', lang) else: text = resolve('no_data',lang) return text
def callback_list_order(update, context): query = update.callback_query order = context.match.group(1) # save the selected order context.chat_data['order'] = order limit = int(context.match.group(2)) if order in ["vaccinations"]: case_list = api.vaccinations_country_list(sort_by=order)[:limit] else: case_list = api.cases_country_list(sort_by=order)[:limit] query.answer() if len(case_list) > 0: text = resolve('list_header', lang(update), resolve("sort_order_"+order, lang(update))) for item in case_list: text += format_list_item(item, order) query.edit_message_text(text=text, parse_mode=ParseMode.MARKDOWN, reply_markup=get_list_keyboard(update, 0, limit, len(case_list) < limit)) else: query.edit_message_text(resolve('no_data', lang(update)), reply_markup=get_list_keyboard(update, 0, limit, len(case_list) < limit))
def command_world(update, context): photo_file = wikidata.cases_world_map() data = api.cases_world() if data: text = format_stats(update, WORLD_IDENT, data) update.message.reply_photo(photo=photo_file, caption=text, parse_mode=ParseMode.MARKDOWN, reply_markup=get_stats_keyboard( update, WORLD_IDENT)) else: update.message.reply_text(resolve('no_data', lang(update)))
def handle_text(update, context): query_string = update.message.text.lower() resolved = resolve_query_string(query_string) if resolved: command_country(update, context, resolved) elif WORLD_IDENT in query_string: command_world(update, context) elif query_string.title() in api.us_states: command_us_state(update, context, query_string) elif query_string.title() in api.de_states: command_de_state(update, context, query_string) else: update.message.reply_text(resolve('unknown_place', lang(update)))
def callback_vacc(update, context): country_code = context.match.group(1) if country_code == WORLD_IDENT: country_code = None data = api.vaccinations_series(country_code) if data: buffer = plot_vaccinations_series(data) update.callback_query.answer() context.bot.send_photo(chat_id=update.callback_query.message.chat_id, photo=buffer) buffer.close() else: update.callback_query.answer() context.bot.send_message(chat_id=update.callback_query.message.chat_id, text=resolve('no_data', lang(update)))
def command_vacc(update, context): if len(context.args) > 0: resolved = resolve_query_string(context.args[0]) if resolved: data = api.vaccinations_series(resolved) elif WORLD_IDENT in context.args[0]: data = api.vaccinations_series() else: update.message.reply_text(resolve('unknown_place', lang(update))) return else: if 'country' in context.chat_data: country_code = context.chat_data['country'] data = api.vaccinations_series(country_code) else: data = api.vaccinations_series() if data: buffer = plot_vaccinations_series(data) update.message.reply_photo(photo=buffer) buffer.close() else: update.message.reply_text(resolve('no_data', lang(update)))
def handle_text(update, context): query_string = update.message.text.lower() if query_string in api.name_map: command_country(update, context, api.name_map[query_string]) elif WORLD_IDENT in query_string: command_world(update, context) elif check_flag(query_string): code = code_from_flag(query_string).lower() if code in api.name_map: command_country(update, context, api.name_map[code]) elif query_string.title() in api.us_states: command_us_state(update, context, query_string) elif query_string.title() in api.de_states: command_de_state(update, context, query_string) else: update.message.reply_text(resolve('unknown_place', lang(update)))
def command_country(update, context, country_code): photo_file = wikidata.cases_country_map(country_code) data = api.cases_country(country_code) if data: text = format_stats(update, country_code, data) if photo_file: update.message.reply_photo(photo=photo_file, caption=text, parse_mode=ParseMode.MARKDOWN, reply_markup=get_stats_keyboard( update, country_code)) else: update.message.reply_markdown(text, reply_markup=get_stats_keyboard( update, country_code)) else: update.message.reply_text(resolve('no_data', lang(update)))
def command_start(update, context): update.message.reply_markdown(resolve('start', lang(update), update.message.from_user.first_name))
def command_help(update, context): update.message.reply_markdown(resolve('help', lang(update)), disable_web_page_preview=True)
def handle_setcountry_start(update, context): update.message.reply_markdown(resolve('setcountry_start', lang(update))) return 1
def command_unsubscribe(update, context): if 'subscribers' in context.bot_data: if update.message.chat.id in context.bot_data['subscribers']: context.bot_data['subscribers'].remove(update.message.chat.id) update.message.reply_markdown(resolve('unsubscribe', lang(update)))
def command_subscribe(update, context): if not 'subscribers' in context.bot_data: context.bot_data['subscribers'] = [update.message.chat.id] elif not update.message.chat.id in context.bot_data['subscribers']: context.bot_data['subscribers'].append(update.message.chat.id) update.message.reply_markdown(resolve('subscribe', lang(update)))
def handle_setcountry_cancel(update, context): update.message.reply_text(resolve('cancel', lang(update))) return ConversationHandler.END