def get_icu_shortpost(self, icu: ICUData) -> List[BotResponse]: tweet_text = f"🏥 Die {self.divi_name} hat Daten über die #Intensivbetten in Deutschland für den " \ f"{icu.date.strftime('%d. %B %Y')} gemeldet.\n\n{format_float(icu.percent_occupied())}% " \ f"({format_int(icu.occupied_beds)}) der " \ f"Betten sind aktuell belegt. " \ f"In {format_noun(icu.occupied_covid, FormattableNoun.BEDS)} " \ f"({format_float(icu.percent_covid())}%) liegen Menschen" \ f" mit #COVID19, davon werden {format_int(icu.covid_ventilated)} beatmet. " \ f"Insgesamt gibt es {format_noun(icu.total_beds(), FormattableNoun.BEDS)} für Erwachsene." post = [BotResponse(tweet_text, [self.viz.icu_graph(0)])] icu_info = self.data.get_icu_global_facts() if icu_info: second_tweet = f"Insgesamt stehen in {icu_info.districts_total} Orten Intensivbetten zur Verfügung. " if icu_info.districts_full: second_tweet += f"Davon haben {icu_info.districts_full} Orte keine freien Intensivbetten mehr für Erwachsene. " if icu_info.districts_low: second_tweet += f"In weiteren {icu_info.districts_low} Orten sind mindestens 90% der Intensivbetten für Erwachsene belegt." if second_tweet: post.append(BotResponse(second_tweet)) return post
async def invite_event(self, room: MatrixRoom, event: InviteMemberEvent): if not event.membership == "invite" or event.state_key != self.matrix.user_id: return self.log.debug(f"Invite Event for {room.name}") resp = await self.matrix.join(room.room_id) if isinstance(resp, JoinError): self.log.error( f"Can't Join {room.room_id} ({room.encrypted}): {JoinError.message}" ) return await self.matrix.sync() self.log.debug(f"Joined room {room.name}") await self.send_response(room.room_id, self.bot.handle_input('Start', room.room_id)) if room.member_count > 2: await self.send_response(room.room_id, [ BotResponse( "Noch ein Hinweis: Da wir hier nicht zu zweit sind reagiere ich nur auf mentions!" ) ])
async def send_bot_response(self, user: str, response: BotResponse): if response.message: images = response.images disable_unicode = not self.bot.get_user_setting( user, BotUserSettings.FORMATTING) max_chars = 2000 if response.choices: max_chars = 640 messages = split_message(adapt_text(str(response), just_strip=disable_unicode), max_chars=max_chars) for i in range(0, len(messages)): buttons = None if response.choices and i == len(messages) - 1: buttons = [] if len(response.choices) > 3: response.choices = response.choices[:3] for choice in response.choices: buttons.append( PostbackButton(choice.label, choice.callback_data)) await self.fb_messenger.send_message(user, messages[i], images=images, buttons=buttons) images = None SENT_MESSAGE_COUNT.inc()
def get_hospitalization_shortpost( self, hospitalization: Hospitalization) -> List[BotResponse]: responses = [ BotResponse( f"🤒 Das {self.rki_name} hat die Hospitalisierungsdaten für den {hospitalization.date.strftime('%d. %B %Y')} veröffentlicht:\n\n" f"Die 7-Tage-Hospitalisierungsinzidenz liegt bei {format_float(hospitalization.incidence)} und in den " f"letzten 7 Tagen wurden {format_noun(hospitalization.cases, FormattableNoun.PERSONS)} ins Krankenhaus " f"aufgenommen. #COVID19") ] # Remove graphic, as it is misleading return responses
def get_vaccination_shortpost(self, vacc: VaccinationData) -> List[BotResponse]: responses = [ BotResponse( f"💉 Das {self.rki_name} hat die Impfdaten für den {vacc.date.strftime('%d. %B %Y')} veröffentlicht.\n\n" f"{format_float(vacc.partial_rate * 100)}% der Bevölkerung haben mindestens eine #Impfung erhalten, " f"{format_float(vacc.full_rate * 100)}% sind vollständig erstimmunisiert. " f"{format_float(vacc.booster_rate * 100)}% haben eine Auffrischungsimpfung erhalten. #COVID19", [self.viz.vaccination_graph(0)]), BotResponse( f"Insgesamt wurden " f"{format_int(vacc.vaccinated_partial)} Erstimpfungen, {format_int(vacc.vaccinated_full)} Zweitimpfungen " f"und {format_int(vacc.vaccinated_booster)} Auffrischungsimpfungen durchgeführt. #COVID19" ), BotResponse( f"Es wurden {format_int(vacc.doses_diff)} Impfdosen verimpft. In den letzten 7 Tagen wurden " f"durchschnittlich täglich {format_int(vacc.avg_speed)} " f"Dosen verabreicht.", [self.viz.vaccination_speed_graph(0)]) ] return responses
def generate_icu_report(self, user: BotUser) -> List[BotResponse]: # Start creating report graphs = [] subscriptions = [] for district_id in user.subscriptions: district = self.covid_data.get_district_data(district_id) if district.icu_data: subscriptions.append(district) subscriptions = self.sort_districts(subscriptions) # Send How-To use if no subscriptions if not subscriptions: return self.get_how_to() message = "<b>Intensivbetten-Bericht vom {date}</b>\n\n"\ .format(date=subscriptions[0].icu_data.date.strftime("%d.%m.%Y")) # Short introduction overview for first country subscribed to countries = list(filter(lambda d: d.type == "Staat", subscriptions)) for c in countries: if self.user_manager.get_user_setting( user.id, BotUserSettings.REPORT_GRAPHICS): graphs.append(self.visualization.icu_graph(c.id)) country = None if countries: country = countries[0] subscriptions = list( filter(lambda x: x.id != country.id, subscriptions)) message += self.get_icu_text(country) # Short summary for each subscribed district if subscriptions and len(subscriptions) > 0: for district in subscriptions: message += self.get_district_icu_summary(district) message += "\n\n" # Add a user message, if some exist user_hint = self.user_hints.get_hint_of_today() if user_hint: message += f"{user_hint}\n\n" # Sources message += '<i>Intensivbettendaten vom <a href="https://intensivregister.de">DIVI-Intensivregister</a>.</i>' \ '\n\n' \ '<i>Sende {info_command} um eine Erl├цuterung ' \ 'der Daten zu erhalten. Ein Service von <a href="https://d-64.org">D64 - Zentrum f├╝r Digitalen ' \ 'Fortschritt</a>.</i>'.format(info_command=self.command_formatter("Info")) message += '\n\nЪДњЪЈйЪЉдЪЈ╗ Sharing is caring ЪЉЕЪЈЙЪДЉЪЈ╝ <a href="https://covidbot.d-64.org">www.covidbot.d-64.org</a>' reports = [BotResponse(message, graphs)] return reports
def get_how_to(self) -> List[BotResponse]: # Send How-To use if no subscriptions return [ BotResponse( "Du hast keine abonnierten Orte. Sende uns einen Ort, um diesen zu abonnieren. Dieser " "taucht dann in deinem Bericht auf.", choices=[ UserChoice( "Hilfe anzeigen", "/hilfe", f"Sende {self.command_formatter('Hilfe')}, um einen ├юberblick ├╝ber " f"die Funktionsweise zu bekommen.") ]) ]
async def send_message_to_users(self, message: str, users: List[Union[str, int]], append_report=False): if users: self.log.error("Can't send a message to specific users!") return if len(message) > 240: self.log.error("Message can't be longer than 240 characters!") return self.write_message([BotResponse(message)])
def get_infection_shortpost(self, district_id: int) -> List[BotResponse]: graphs = [ self.viz.incidence_graph(district_id), self.viz.infections_graph(district_id) ] district = self.data.get_district_data(district_id) date_str = "Am " + district.date.strftime('%d. %B %Y') if district.date == datetime.date.today() - datetime.timedelta(days=1): date_str = "Heute sind leider noch keine Daten verfügbar. Gestern" tweet_text = f"🦠 {date_str} wurden " \ f"{format_noun(district.new_cases, FormattableNoun.NEW_INFECTIONS, hashtag='#')} " \ f"{format_data_trend(district.cases_trend)} und " \ f"{format_noun(district.new_deaths, FormattableNoun.DEATHS)} " \ f"{format_data_trend(district.deaths_trend)} in {district.name} gemeldet. Die #Inzidenz liegt " \ f"bei {format_float(district.incidence)} {format_data_trend(district.incidence_trend)}. #COVID19" # Maximum of 4 graphs allowed #if district.vaccinations: # graphs.append(self.viz.vaccination_graph(district_id)) if district.icu_data: graphs.append(self.viz.icu_graph(district_id)) return [BotResponse(tweet_text, graphs)]
async def send_message_to_users(self, message: str, users: List[Union[str, int]]): for user in users: await self.send_response(user, [BotResponse(message)])
def format_response(bot_response: BotResponse, just_strip: bool): bot_response.message = adapt_text(str(bot_response), just_strip=just_strip) return bot_response
def generate_infection_report(self, user: BotUser) -> List[BotResponse]: # Send How-To use if no subscriptions if not user.subscriptions: return self.get_how_to() # Start creating report graphs = [] subscriptions = [] for district_id in user.subscriptions: base_data = self.covid_data.get_district_data(district_id) if base_data is not None: subscriptions.append(base_data) else: self.log.warn(f"No base data for {district_id}") subscriptions = self.sort_districts(subscriptions) message = "<b>Corona-Bericht vom {date}</b>\n\n".format( date=subscriptions[0].date.strftime("%d.%m.%Y")) # Short introduction overview for first country subscribed to countries = list(filter(lambda d: d.type == "Staat", subscriptions)) for c in countries: if self.user_manager.get_user_setting( user.id, BotUserSettings.REPORT_GRAPHICS): graphs.append(self.visualization.infections_graph(c.id)) # Remove graphic, as it is misleading #graphs.append(self.visualization.hospitalization_graph(c.id)) country = None if countries: country = countries[0] subscriptions = list( filter(lambda x: x.id != country.id, subscriptions)) message += self.get_infection_text(country) # Short summary for each subscribed district if subscriptions and len(subscriptions) > 0: every_graph = self.user_manager.get_user_setting( user.id, BotUserSettings.REPORT_ALL_INFECTION_GRAPHS) for district in subscriptions: message += self.get_district_summary( district, self.user_manager.get_user_setting( user.id, BotUserSettings.REPORT_INCLUDE_ICU), self.user_manager.get_user_setting( user.id, BotUserSettings.REPORT_INCLUDE_VACCINATION)) if every_graph: graphs.append( self.visualization.infections_graph(district.id)) message += "\n\n" # Generate multi-incidence graph for up to 8 districts if self.user_manager.get_user_setting(user.id, BotUserSettings.REPORT_GRAPHICS): districts = user.subscriptions[-8:] if 0 in user.subscriptions and 0 not in districts: districts[0] = 0 graphs.append(self.visualization.multi_incidence_graph(districts)) # Add some information regarding vaccinations, if available if country and country.vaccinations and \ self.user_manager.get_user_setting(user.id, BotUserSettings.REPORT_INCLUDE_VACCINATION): message += self.get_vacc_text(country) if self.user_manager.get_user_setting( user.id, BotUserSettings.REPORT_GRAPHICS): graphs.append(self.visualization.vaccination_graph(country.id)) if self.user_manager.get_user_setting( user.id, BotUserSettings.REPORT_EXTENSIVE_GRAPHICS): graphs.append( self.visualization.vaccination_speed_graph(country.id)) # Add some information regarding ICU, if available if country and country.icu_data and self.user_manager.get_user_setting( user.id, BotUserSettings.REPORT_INCLUDE_ICU): message += self.get_icu_text(country) if self.user_manager.get_user_setting( user.id, BotUserSettings.REPORT_EXTENSIVE_GRAPHICS): graphs.append(self.visualization.icu_graph(country.id)) # Add a user message, if some exist user_hint = self.user_hints.get_hint_of_today() if user_hint: message += f"{user_hint}\n\n" # Sources message += '<i>Daten vom Robert Koch-Institut (RKI), Lizenz: dl-de/by-2-0, weitere Informationen findest Du' \ ' im <a href="https://corona.rki.de/">Dashboard des RKI</a> und dem ' \ '<a href="https://impfdashboard.de/">Impfdashboard</a>. ' \ 'Intensivbettendaten vom <a href="https://intensivregister.de">DIVI-Intensivregister</a>.</i>' \ '\n\n' \ '<i>Sende {info_command} um eine Erl├цuterung ' \ 'der Daten zu erhalten. Ein Service von <a href="https://d-64.org">D64 - Zentrum f├╝r Digitalen ' \ 'Fortschritt</a>.</i>'.format(info_command=self.command_formatter("Info")) message += '\n\nЪДњЪЈйЪЉдЪЈ╗ Sharing is caring ЪЉЕЪЈЙЪДЉЪЈ╝ <a href="https://covidbot.d-64.org">www.covidbot.d-64.org</a>' reports = [BotResponse(message, graphs)] return reports
def generate_vaccination_report(self, user: BotUser) -> List[BotResponse]: # Start creating report graphs = [] subscriptions = [] for district_id in user.subscriptions: district = self.covid_data.get_district_data(district_id) # Add parent, if no vaccination data available if not district.vaccinations: if district.parent in [d.id for d in subscriptions]: continue district = self.covid_data.get_district_data(district.parent) if district.vaccinations: subscriptions.append(district) # Send How-To use if no subscriptions if not user.subscriptions: return self.get_how_to() subscriptions = self.sort_districts(subscriptions) message = "<b>Impfbericht zum {date}</b>\n\n".format( date=subscriptions[0].vaccinations.date.strftime("%d.%m.%Y")) # Short introduction overview for first country subscribed to countries = list(filter(lambda d: d.type == "Staat", subscriptions)) for c in countries: if self.user_manager.get_user_setting( user.id, BotUserSettings.REPORT_GRAPHICS): graphs.append(self.visualization.vaccination_graph(c.id)) graphs.append(self.visualization.vaccination_speed_graph(c.id)) country = None if countries: country = countries[0] subscriptions = list( filter(lambda x: x.id != country.id, subscriptions)) message += self.get_vacc_text(country) # Short summary for each subscribed district if subscriptions and len(subscriptions) > 0: for district in subscriptions: message += self.get_district_vacc_summary(district) message += "\n\n" # Add a user message, if some exist user_hint = self.user_hints.get_hint_of_today() if user_hint: message += f"{user_hint}\n\n" # Sources message += '<i>Daten vom Robert Koch-Institut (RKI) und BMG, Lizenz: dl-de/by-2-0, weitere Informationen findest Du' \ ' im <a href="https://impfdashboard.de/">Impfdashboard</a>.</i>' \ '\n\n' \ '<i>Sende {info_command} um eine Erl├цuterung ' \ 'der Daten zu erhalten. Ein Service von <a href="https://d-64.org">D64 - Zentrum f├╝r Digitalen ' \ 'Fortschritt</a>.</i>'.format(info_command=self.command_formatter("Info")) message += '\n\nЪДњЪЈйЪЉдЪЈ╗ Sharing is caring ЪЉЕЪЈЙЪДЉЪЈ╝ <a href="https://covidbot.d-64.org">www.covidbot.d-64.org</a>' reports = [BotResponse(message, graphs)] return reports
def message_developer(self, message: str): if self.send_message(self.dev_chat_id, [BotResponse(message)]): return True return False
async def send_unconfirmed_reports(self) -> None: germany = self.data.get_country_data() if not germany: raise ValueError("Could not find data for Germany") # Do not tweet at night, so we show up more recently in the morning if datetime.datetime.now().hour < 6: return if self.user_manager.get_user( self.user_id).created.date() == datetime.date.today(): return # Infections last_update = self.user_manager.get_last_updates( self.user_id, MessageType.CASES_GERMANY) if not last_update or last_update.date() < germany.date: tweet_text = f"🦠 Das {self.rki_name} hat für den {germany.date.strftime('%d. %B %Y')} neue Infektionszahlen veröffentlicht.\n\n" \ f"Es wurden {format_noun(germany.new_cases, FormattableNoun.NEW_INFECTIONS, hashtag='#')} " \ f"{format_data_trend(germany.cases_trend)} und " \ f"{format_noun(germany.new_deaths, FormattableNoun.DEATHS)} " \ f"{format_data_trend(germany.deaths_trend)} in Deutschland gemeldet. Die bundesweite #Inzidenz liegt " \ f"bei {format_float(germany.incidence)} {format_data_trend(germany.incidence_trend)}, der " \ f"aktuelle R-Wert beträgt {format_float(germany.r_value.r_value_7day)}. #COVID19" if self.no_write: print(f"Sent message: {tweet_text}") self.user_manager.add_sent_report(self.user_id, MessageType.CASES_GERMANY) elif self.write_message([ BotResponse(tweet_text, [ self.viz.infections_graph(0), self.viz.incidence_graph(0) ]) ]): self.log.info("Tweet was successfully sent") self.user_manager.add_sent_report(self.user_id, MessageType.CASES_GERMANY) # Vaccinations last_update = self.user_manager.get_last_updates( self.user_id, MessageType.VACCINATION_GERMANY) if not last_update or (germany.vaccinations and last_update < germany.vaccinations.last_update): posts = self.get_vaccination_shortpost(germany.vaccinations) if self.no_write: print(f"Sent message: {posts[0].message}") self.user_manager.add_sent_report( self.user_id, MessageType.VACCINATION_GERMANY) elif self.write_message(posts): self.user_manager.add_sent_report( self.user_id, MessageType.VACCINATION_GERMANY) self.log.info("Tweet was successfully sent") # ICU last_update = self.user_manager.get_last_updates( self.user_id, MessageType.ICU_GERMANY) if not last_update or last_update < germany.icu_data.last_update: posts = self.get_icu_shortpost(germany.icu_data) if self.no_write: print(f"Sent message: {posts[1].message}") self.user_manager.add_sent_report(self.user_id, MessageType.ICU_GERMANY) elif self.write_message(posts): self.log.info("Tweet was successfully sent") self.user_manager.add_sent_report(self.user_id, MessageType.ICU_GERMANY) # Hospitalization last_update = self.user_manager.get_last_updates( self.user_id, MessageType.HOSPITALIZATION_GERMANY) if not last_update or last_update.date( ) < germany.hospitalisation.date: posts = self.get_hospitalization_shortpost(germany.hospitalisation) if self.no_write: print(f"Sent message: {posts[0].message}") self.user_manager.add_sent_report( self.user_id, MessageType.HOSPITALIZATION_GERMANY) elif self.write_message(posts): self.log.info("Tweet was successfully sent") self.user_manager.add_sent_report( self.user_id, MessageType.HOSPITALIZATION_GERMANY)