def activate_poll(poll_id): if request.method == 'GET': with my_session_scope( my_database) as session: # type: MyDatabaseSession poll = session.get_poll_by_id(poll_id) if poll is None or poll.state != PollState.prepared: return render_template('admin_message.html', msg="poll_not_prepared") return render_template('admin_activate_poll.html', label=poll.label, poll_id=poll.poll_id) elif request.method == 'POST': request_tokens = json.loads(request.form["tokens"]) tokens = request_tokens['tokens'] attendees = request_tokens['users'] with my_session_scope( my_database) as session: # type: MyDatabaseSession if session.activate_poll(poll_id, tokens, attendees): return render_template('admin_message.html', msg="poll_activated", poll_id=poll_id) else: return render_template('admin_message.html', msg="poll_activate_error", poll_id=poll_id)
def answer_subscribe_channel(self, update: Update, context: CallbackContext): self.remove_all_inline_keyboards(update, context) chat_id = update.effective_chat.id with my_session_scope( self.my_database) as session: # type: MyDatabaseSession user = session.get_user_by_chat_id(chat_id) channel = self.get_channel_from_update(session, update, context) if user is None: context.bot.send_message( chat_id=chat_id, text=self.get_message_user_not_known()) return ConversationHandler.END elif channel is not None: if channel.name in user.channels: answer = "Du hast diesen Kanal bereits abonniert." context.bot.send_message(chat_id=chat_id, text=answer) return ConversationHandler.END else: session.add_channel(chat_id, channel) userLogger.info("User {0} subscribed channel {1}.".format( chat_id, channel.name)) answer = "Kanal <b>" + channel.name + "</b> wurde abonniert." context.bot.send_message(chat_id=chat_id, text=answer, parse_mode=ParseMode.HTML) return ConversationHandler.END else: answer = "Kanal nicht vorhanden. Bitte anderen Kanal eingeben." unsubscribed_channels = session.get_unsubscribed_channels( chat_id) reply_markup = TelegramShoutoutBot.create_channel_keyboard( unsubscribed_channels, CB_SUBSCRIBE_CANCEL) context.bot.send_message_keyboard(chat_id=chat_id, text=answer, reply_markup=reply_markup)
def cmd_send(self, update: Update, context: CallbackContext): self.remove_all_inline_keyboards(update, context) chat_id = update.effective_chat.id with my_session_scope( self.my_database) as session: # type: MyDatabaseSession user = session.get_user_by_chat_id(chat_id) if user is None: context.bot.send_message( chat_id=chat_id, text=self.get_message_user_not_known()) return ConversationHandler.END elif user.ldap_account is not None and self.ldap_access.check_usergroup( user.ldap_account): send_data: SendData = SendData() context.user_data["send"] = send_data accessible_channels: List[ Channel] = self.get_accessible_channels(session, user) answer = "<b>Nachricht senden</b>\n\n" \ "Bitte Kanal eingeben, an den die Nachricht gesendet werden soll.\n\n" \ "Verfügbare Kanäle:\n" + TelegramShoutoutBot.create_channel_list(accessible_channels) reply_markup = TelegramShoutoutBot.create_channel_keyboard( accessible_channels, CB_SEND_CANCEL) send_data.botm_choose_channel = context.bot.send_message_keyboard( chat_id=chat_id, text=answer, reply_markup=reply_markup, parse_mode=ParseMode.HTML) return SEND_CHANNEL else: answer = "Du benötigst Admin-Rechte um Nachrichten zu verschicken." context.bot.send_message(chat_id=chat_id, text=answer) return ConversationHandler.END
def submit_vote(poll_id): token = request.form['token'] answers = [int(x) for x in request.form.getlist('answer')] with my_session_scope(my_database) as session: # type: MyDatabaseSession poll: Poll = session.get_poll_by_id(poll_id) vote: Vote = session.get_vote(poll_id, token) if not vote: return render_template('message.html', poll_label=poll.label, state="token_invalid") if poll.state != PollState.active: return render_template('message.html', poll_label=poll.label, state="not_active") # Validation of vote if len(answers) > poll.numVotes: return render_template('message.html', poll_label=poll.label, state="too_many_votes") if len(answers) > 1 and session.contains_exclusive_answer(answers): return render_template('message.html', poll_label=poll.label, state="invalid_combination") vote.answerOptions.clear() vote.association_ids.extend(answers) return render_template('message.html', poll_label=poll.label, state="successful")
def cmd_admin(self, update: Update, context: CallbackContext): self.remove_all_inline_keyboards(update, context) chat_id = update.effective_chat.id with my_session_scope( self.my_database) as session: # type: MyDatabaseSession user = session.get_user_by_chat_id(chat_id) if user is None: answer = self.get_message_user_not_known() elif user.ldap_account is None: answer = "Du hast <i>keinen</i> DPSG-Account mit deinem Telegram-Zugang verbunden." elif self.ldap_access.check_usergroup(user.ldap_account): accessible_channels: List[ Channel] = self.get_accessible_channels(session, user) answer = "Du hast einen DPSG-Account mit deinem Telegram-Zugang verbunden " \ "und hast Admin-Rechte in Telegram.\n\n" \ "Du kannst derzeit die folgenden Kanäle beschreiben: \n" answer += TelegramShoutoutBot.create_channel_list( accessible_channels) answer += "\nFalls du Zugang zu weiteren Kanälen brauchst, wende dich ans Webteam." else: answer = "Du hast einen DPSG-Account mit deinem Telegram-Zugang verbunden, " \ "hast aber noch keine Admin-Rechte in Telegram.\n" \ "Wende dich mit deiner Chat-ID {0} ans Webteam um Admin-Rechte zu erhalten.".format(chat_id) context.bot.send_message(chat_id=chat_id, text=answer, parse_mode=ParseMode.HTML)
def answer_unsubscribe_channel(self, update: Update, context: CallbackContext): self.remove_all_inline_keyboards(update, context) chat_id = update.effective_chat.id with my_session_scope( self.my_database) as session: # type: MyDatabaseSession user = session.get_user_by_chat_id(chat_id) channel = self.get_channel_from_update(session, update, context) if user is None: context.bot.send_message( chat_id=chat_id, text=self.get_message_user_not_known()) return ConversationHandler.END elif channel is None: answer = "Kanal nicht vorhanden. " \ "Bitte anderen Kanal eingeben oder Abbrechen mit /cancel." context.bot.send_message(chat_id=chat_id, text=answer) # no return statement (stay in same state) elif channel not in user.channels.values(): answer = "Kanal nicht abonniert. " \ "Bitte anderen Kanal eingeben oder Abbrechen mit /cancel." context.bot.send_message(chat_id=chat_id, text=answer) # no return statement (stay in same state) elif channel.mandatory: answer = "Dieser Kanal ist immer abonniert und kann nicht abbestellt werden." context.bot.send_message(chat_id=chat_id, text=answer) # no return statement (stay in same state) else: session.remove_channel(chat_id, channel) userLogger.info("User {0} desubscribed channel {1}.".format( chat_id, channel.name)) answer = "Kanal <b>" + channel.name + "</b> wurde deabonniert." context.bot.send_message(chat_id=chat_id, text=answer, parse_mode=ParseMode.HTML) return ConversationHandler.END
def cmd_unsubscribe(self, update: Update, context: CallbackContext): self.remove_all_inline_keyboards(update, context) chat_id = update.effective_chat.id with my_session_scope( self.my_database) as session: # type: MyDatabaseSession user = session.get_user_by_chat_id(chat_id) if user is None: context.bot.send_message( chat_id=chat_id, text=self.get_message_user_not_known()) return ConversationHandler.END else: # Filter out mandatory channels from list to select from subscribed_channels = list( filter(lambda channel: not channel.mandatory, user.channels.values())) answer = "<b>Kanal deabonnieren</b>\n\n"\ "Kanal eingeben, der deabonniert werden soll oder Abbrechen mit /cancel.\n\n" \ "<b>Bereits abonnierte Kanäle:</b>\n" + \ TelegramShoutoutBot.create_channel_list(subscribed_channels) reply_markup = TelegramShoutoutBot.create_channel_keyboard( subscribed_channels, CB_UNSUBSCRIBE_CANCEL) context.bot.send_message_keyboard(chat_id=chat_id, text=answer, reply_markup=reply_markup, parse_mode=ParseMode.HTML) return UNSUBSCRIBE_CHANNEL
def cmd_stop(self, update: Update, context: CallbackContext): self.remove_all_inline_keyboards(update, context) chat_id = update.effective_chat.id with my_session_scope(self.my_database) as session: session.delete_user(chat_id) answer = "Alle Daten gelöscht. Der Bot wird keine weiteren Nachrichten schicken.\n" \ "Falls du wieder Nachrichten erhalten möchtest, schreibe /start." context.bot.send_message(chat_id=chat_id, text=answer)
def admin_overview(): with my_session_scope(my_database) as session: # type: MyDatabaseSession prepared_polls = session.get_polls(PollState.prepared) active_polls = session.get_polls(PollState.active) closed_polls = session.get_polls(PollState.closed) return render_template('admin_overview.html', prepared_polls=prepared_polls, active_polls=active_polls, closed_polls=closed_polls)
def answer_confirm(self, update: Update, context: CallbackContext): self.remove_all_inline_keyboards(update, context) chat = update.effective_chat send_data = context.user_data["send"] # type: SendData updated_text = "Nachrichten werden versendet" send_data.botm_confirmation.result(10).edit_text( text=updated_text, parse_mode=ParseMode.HTML) channel_name = send_data.channel log_messages_strings = list( map(lambda msg: msg.__dict__, send_data.messages)) log_message_format = "Sent message by user {0} ({1}, {2} {3}) to channel {4}: {5}" adminLogger.info( log_message_format.format(chat.id, chat.username, chat.first_name, chat.last_name, channel_name, log_messages_strings)) with my_session_scope( self.my_database) as session: # type: MyDatabaseSession # Verify permissions again to be safe (the conversation could be running for longer) user = session.get_user_by_chat_id(chat.id) channel = session.get_channel_by_name(channel_name) if user is None or user.ldap_account is None or not self.ldap_access.check_usergroup(user.ldap_account) or \ not self.ldap_access.check_filter(user.ldap_account, channel.ldap_filter): adminLogger.warning( "Stopped message sending because of insufficient permissions." ) answer = "Du hast keine Berechtigung zum Nachrichtenversand." context.bot.send_message(chat_id=chat.id, text=answer) return ConversationHandler.END # Send message out to users subscriber_count = 0 last_message = None for user in session.get_users(): if channel_name in user.channels: subscriber_count += 1 for message in send_data.messages: last_message = TelegramShoutoutBot.resend_message( user.chat_id, message, context) if last_message is not None: promise_result = last_message.result(60) message_counter = len(send_data.messages) * subscriber_count if promise_result is not None: answer = "Nachrichten erfolgreich zugestellt. " \ "Es wurden insgesamt <b>{0}</b> Nachrichten an <b>{1}</b> Abonnenten versendet." else: answer = "Nicht alle Nachrichten konnten innerhalb von 60 Sekunden zugestellt werden. " \ "Es sollten insgesamt <b>{0}</b> an <b>{1}</b> Abonnenten Nachrichten versendet werden." context.bot.send_message(chat_id=chat.id, text=answer.format( message_counter, subscriber_count), parse_mode=ParseMode.HTML) adminLogger.info(answer) return ConversationHandler.END
def cmd_start(self, update: Update, context: CallbackContext): self.remove_all_inline_keyboards(update, context) chat = update.effective_chat with my_session_scope( self.my_database) as session: # type: MyDatabaseSession session.add_user(chat.id, chat.username, chat.first_name, chat.last_name) context.bot.send_message( chat_id=chat.id, parse_mode=ParseMode.HTML, text='<b>Herzlich willkommen!</b>\n\n' 'Mittels /subscribe kannst du jetzt zusätzliche Kanäle abbonieren.\n' 'Mit /help werden dir alle Befehle angezeigt.')
def vote_form(poll_id): with my_session_scope(my_database) as session: # type: MyDatabaseSession poll: Poll = session.get_poll_by_id(poll_id) if poll.state == PollState.prepared: return render_template('message.html', state="not_active", poll_label=poll.label, poll_id=poll_id) elif poll.state == PollState.active: return render_template('index.html', poll=poll) else: poll_results = session.get_results(poll_id) return render_template('poll_results.html', poll=poll, poll_results=poll_results)
def cmd_unregister(self, update: Update, context: CallbackContext): self.remove_all_inline_keyboards(update, context) chat_id = update.effective_chat.id with my_session_scope( self.my_database) as session: # type: MyDatabaseSession user = session.get_user_by_chat_id(chat_id) if user is None: answer = self.get_message_user_not_known() elif user.ldap_account is None: answer = "Du hast keinen DPSG-Account mit deinem Telegram-Zugang verbunden. " \ "Verwende /register um einen Account zu verbinden." else: ldap_account_name = user.ldap_account session.remove_ldap(chat_id) userLogger.info( "User {0} removed his account connection to {1}.".format( chat_id, ldap_account_name)) answer = "Account-Zuordnung entfernt" context.bot.send_message(chat_id=chat_id, text=answer)
def cmd_register(self, update: Update, context: CallbackContext): self.remove_all_inline_keyboards(update, context) chat_id = update.effective_chat.id with my_session_scope( self.my_database) as session: # type: MyDatabaseSession user = session.get_user_by_chat_id(chat_id) if user is None: answer = self.get_message_user_not_known() elif user.ldap_account is not None: answer = "Du hast bereits einen DPSG-Account mit deinem Telegram-Zugang verbunden. " \ "Verwende /unregister um diese Verbindung zu lösen." else: letters_and_digits = string.ascii_letters + string.digits token = ''.join( random.choice(letters_and_digits) for _ in range(20)) user.ldap_register_token = token session.commit() answer = "Bitte klicke auf den folgenden Link:\n" \ "{0}{1}register/{2}?token={3}".format(Conf.url_host, Conf.url_path, chat_id, token) context.bot.send_message(chat_id=chat_id, text=answer)
def answer_channel(self, update: Update, context: CallbackContext): self.remove_all_inline_keyboards(update, context) chat_id = update.effective_chat.id with my_session_scope( self.my_database) as session: # type: MyDatabaseSession user = session.get_user_by_chat_id(chat_id) channel = self.get_channel_from_update(session, update, context) if user is None: context.bot.send_message( chat_id=chat_id, text=self.get_message_user_not_known()) return ConversationHandler.END elif channel is None: answer = "Kanal nicht vorhanden. Bitte anderen Kanal eingeben." context.bot.send_message(chat_id=chat_id, text=answer) # no return statement (stay in same state) else: if channel.ldap_filter is None or len( channel.ldap_filter) == 0: logger.warning( "No LDAP filter configured for channel {0}. Denying access." .format(channel.name)) if self.ldap_access.check_filter(user.ldap_account, channel.ldap_filter): send_data = context.user_data["send"] send_data.channel = channel.name updated_text = "<b>Nachricht senden</b>\n\n" \ "Ausgewählter Kanal: <b>" + channel.name + "</b>" send_data.botm_choose_channel.result(10).edit_text( text=updated_text, parse_mode=ParseMode.HTML) answer = "Nachrichten eingeben, die gesendet werden soll." context.bot.send_message(chat_id=chat_id, text=answer) return SEND_MESSAGE else: answer = "Du hast keine Berechtigung an diesen Kanal zu schreiben." all_channels = session.get_channels() reply_markup = TelegramShoutoutBot.create_channel_keyboard( all_channels, CB_SEND_CANCEL) context.bot.send_message_keyboard( chat_id=chat_id, text=answer, reply_markup=reply_markup)
def register_login(chat_id): token = request.form['token'] username = request.form['username'] password = request.form['password'] ldap_account = Conf.ldap_username_template.format(username) if not ldap_access.check_credentials(ldap_account, password): return render_template('register_login_fail.html', reason="ldap", chat_id=chat_id, token=token) with db.my_session_scope(my_database) as session: # type: db.MyDatabaseSession user = session.get_user_by_chat_id(chat_id) if user is None: return render_template('register_login_fail.html', reason="chat_id", chat_id=chat_id, token=token) if user.ldap_register_token != token: return render_template('register_login_fail.html', reason="token", chat_id=chat_id, token=token) user.ldap_account = ldap_account user.ldap_register_token = None session.commit() log_message_format = "Registered chat_id {0} with token {1} for LDAP-User {2}" webLogger.info(log_message_format.format(chat_id, token, username)) return render_template('register_login_success.html', chat_id=chat_id, token=token, username=username)
def new_poll(): if request.method == 'GET': return render_template('admin_new_poll.html', poll_types=PollType.__members__.items()) elif request.method == 'POST': label = request.form["label"] poll_type = PollType[request.form["type"]] if poll_type == PollType.multiPersonVote: num_votes = request.form["numVotes"] else: num_votes = 1 request_answers: List[str] = request.form.getlist("answer[]") answer_options = [x.strip() for x in request_answers if x.strip()] with my_session_scope( my_database) as session: # type: MyDatabaseSession poll = session.add_poll(label, poll_type, num_votes, answer_options) if poll_type == PollType.multiPersonVote: answer_option_empty = AnswerOption(EMPTY_VOTE) answer_option_empty.exclusive = True poll.answer_options.append(answer_option_empty) return render_template('admin_message.html', msg="create_success", poll_id=poll.poll_id)
def close_poll(poll_id): with my_session_scope(my_database) as session: # type: MyDatabaseSession session.close_poll(poll_id) return render_template('admin_message.html', msg="poll_closed", poll_id=poll_id)