Example #1
0
def confirm_email(user: User, update: Update, context: CallbackContext):
    available_inputs = [
        user.language.get(Token.YES),
        user.language.get(Token.NO),
        user.language.get(Token.CANCEL)
    ]

    message = update.message.text

    if message not in available_inputs:
        reply_to(user,
                 update,
                 user.language.get(Token.ENTER_VALID_COMMAND),
                 reply_markup=Keyboard.email_verify_keyboard(user.language))
        return

    if message == user.language.get(Token.YES):
        email = context.user_data["email"]
        user.email = email
        update_user(user)
        _clear_context(context)
        reply_html(user, update,
                   user.language.get(Token.EMAIL_SET) % email,
                   Keyboard.main(user))
        mwelog.info(f"{user.username} confirms {email} is correct")
        try:
            context.bot.send_message(
                mwexpress_config.moderator,
                f"{user.username} set their email as: {email}")
        except Exception as ex:
            mwelog.exception(ex)
    else:
        _clear_context(context)
        reply_to(user, update, user.language.get(Token.EMAIL_CANCELLED),
                 Keyboard.main(user))
Example #2
0
def ask_for_email(user: User, update: Update, context: CallbackContext):
    mwelog.info(f"Asked for email from {user.username}")
    context.user_data["sub_state"] = "typing_email"
    reply_html(user,
               update,
               user.language.get(Token.ADD_EMAIL_START),
               reply_markup=Keyboard.remove())
Example #3
0
def unmute_everyone():
    mwelog.info("Unmuting everyone")
    all_users = get_all_users()
    for user in all_users:
        user.muted = False
    session = database.get_session()
    database.commit(session)
Example #4
0
def change_user_language(user: User, language: Language) -> None:
    session = database.get_session()
    user.language = language
    database.commit(session)
    mwelog.info("User {user_name} changed language to: {language}",
                user_name=user.username,
                user_id=user.id,
                language=str(user.language))
Example #5
0
def language_change_handler(user: User, update: Update,
                            context: CallbackContext) -> None:
    mwelog.info(
        "User {user_name} is changing language, current language: {language}",
        user_name=user.username,
        user_id=user.id,
        language=str(user.language))
    set_state(context, State.CHANGING_LANGUAGE)
    reply_to(user, update, user.language.get(Token.SELECT_LANGUAGE),
             Keyboard.language_selection(user.language))
Example #6
0
def clear_scores_for_today():
    mwelog.info("Clearing scores for today")
    all_users = get_all_users()
    for user in all_users:
        user.score_today_en = 0
        user.score_today_tr = 0
        user.score_today_it = 0
    session = database.get_session()
    database.commit(session)
    scoreboard.clear()
Example #7
0
    def __init__(self):
        self.engine = create_engine(mwexpress_config.db_connection_string,
                                    echo=False)
        self.Session = scoped_session(sessionmaker(bind=self.engine))
        self.session = self.Session()
        self.commit_lock = threading.Lock()

        # noinspection PyUnresolvedReferences
        from models import User, Mwe, Submission, Review, FeedbackData, Achievement, Base
        # Base.metadata.drop_all(engine)
        Base.metadata.create_all(self.engine)
        mwelog.info("Database initialized.")
Example #8
0
def reply_to(user: User, update: Update, message: str,
             reply_markup: Optional[ReplyMarkup] = None) -> None:
    """
    Sends a reply back to user.

    :param user: User to reply to
    :param update: This object is used to send reply
    :param message: The message to reply with
    :param reply_markup: The keyboard markup to set with the reply
    """
    mwelog.info("Bot replied to {user_name} with: {message}",
                user_name=user.username, user_id=user.id, message=message)
    update.message.reply_text(text=message, parse_mode=ParseMode.MARKDOWN,
                              reply_markup=reply_markup)
Example #9
0
def claim_email_announcement(update: Update, context: CallbackContext):
    mwelog.info("Sending claim email announcement to champions")
    user = get_user_from_update(update)
    if user.id == mwexpress_config.moderator or user.id == 1065263859:
        for user in get_all_users():
            if user.became_champion:
                try:
                    mwelog.info(
                        f"Sending claim email message to {user.username}")
                    context.bot.send_sticker(user.id, EXCITED_STICKER)
                    context.bot.send_message(
                        user.id, user.language.get(Token.CHAMP_BUT_NO_EMAIL))
                    time.sleep(0.5)
                except Exception as ex:
                    mwelog.exception(str(ex))
Example #10
0
def send_game_started_again_with_awards(update: Update,
                                        context: CallbackContext):
    mwelog.info("Sending game started again message to all users")
    user = get_user_from_update(update)
    if user.id == mwexpress_config.moderator or user.id == 1065263859:
        for user in get_all_users():
            try:
                mwelog.info(
                    f"Sending game started again message to {user.username}")
                context.bot.send_sticker(user.id, EXCITED_STICKER)
                send_message_to_user(
                    context.bot, user,
                    user.language.get(Token.GAME_STARTED_AGAIN_ANNOUNCEMENT))
                time.sleep(0.5)
            except Exception as ex:
                mwelog.exception(str(ex))
Example #11
0
def check_email_and_ask_confirmation(user: User, update: Update,
                                     context: CallbackContext):
    email_regex = r'(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)'
    email = update.message.text
    mwelog.info(f"Email got from {user.username}: {email}")
    if not re.match(email_regex, email):
        reply_to(user,
                 update,
                 user.language.get(Token.INVALID_EMAIL),
                 reply_markup=Keyboard.remove())
    else:
        context.user_data["sub_state"] = "confirming_email"
        context.user_data["email"] = email
        reply_html(user,
                   update,
                   user.language.get(Token.CONFIRM_EMAIL) % email,
                   reply_markup=Keyboard.email_verify_keyboard(user.language))
Example #12
0
def load_initial_data():
    with open("idioms.json", encoding="utf-8") as initial_idioms_file:
        initial_idioms = loads(initial_idioms_file.read())
        for i in range(len(initial_idioms)):
            initial_idioms[i]['day'] = datetime.fromisoformat(
                initial_idioms[i]['day']).date()
            if initial_idioms[i]['category'] == 'VID':
                initial_idioms[i]['category'] = MweCategory.VID
            elif initial_idioms[i]['category'] == 'VPC':
                initial_idioms[i]['category'] = MweCategory.VPC
            else:
                raise ValueError(
                    f'Category cannot be {initial_idioms[i]["category"]}')

        for initial_mwe in initial_idioms:
            mwe = get_date_mwe(mwexpress_config.language, initial_mwe['day'])
            if mwe is None:
                add_mwe(initial_mwe['name'], initial_mwe['meaning'],
                        mwexpress_config.language, initial_mwe['day'],
                        initial_mwe['lemmas'], initial_mwe['category'])
                mwelog.info(f'Added mwe: {initial_mwe["name"]}')
Example #13
0
def send_game_starting_message_to_all() -> None:
    mwelog.info("Sending game started message to all users")
    unmute_everyone()
    all_users = get_all_users()
    for user in all_users:
        try:
            mwexpress_bot.bot.send_sticker(user.id, GOOD_MORNING_STICKER)
            send_message_to_user(mwexpress_bot.bot, user,
                                 user.language.get(Token.GAME_STARTED))
            todays_mwe = get_todays_mwe(user.language)
            send_message_to_user(
                mwexpress_bot.bot,
                user,
                user.language.get(Token.TODAYS_MWE_REPLY_TEXT) %
                (todays_mwe.name, todays_mwe.meaning),
                reply_markup=Keyboard.main(user),
                parse_mode=ParseMode.HTML)
            time.sleep(0.3)
        except Exception as ex:
            mwelog.exception(str(ex))
    mwelog.info("Sent game started message to all users")
Example #14
0
 def _send_notification(self,
                        context: CallbackContext,
                        user_id: int,
                        message: str,
                        not_type: NotificationType,
                        sticker: Optional[str] = None,
                        parse_mode: Optional[str] = None):
     if not self._history_contains_notification(user_id, not_type):
         try:
             mwelog.info("Sending {not_type} to {user_id}",
                         not_type=str(not_type),
                         user_id=user_id)
             notification = SentNotification(user_id, not_type,
                                             datetime.now())
             self._notification_history[user_id].append(notification)
             if sticker is not None:
                 context.bot.send_sticker(user_id, sticker)
             context.bot.send_message(user_id,
                                      message,
                                      parse_mode=parse_mode)
         except Exception as ex:
             mwelog.exception(str(ex))
Example #15
0
def award_champion():
    mwelog.info("Awarding champion")
    boards = scoreboard.scoreboards
    for language in Language.ENGLISH, Language.TURKISH, Language.ITALIAN:
        if len(boards[language]) > 0:
            first_user = get_user(boards[language][0].user_id)
            mwelog.info("{username} is the champion",
                        username=first_user.username)
            award_achievement(first_user, AchievementType.CHAMPION)
            try:
                mwexpress_bot.bot.send_sticker(first_user.id,
                                               ACHIEVEMENT_STICKER)
                send_message_to_user(mwexpress_bot.bot,
                                     first_user,
                                     first_user.language.get(
                                         Token.CHAMPION_ACH_CONGRATS_MSG),
                                     parse_mode=ParseMode.HTML)
                if mwexpress_config.email_enabled:
                    if first_user.email is None:
                        send_message_to_user(
                            mwexpress_bot.bot,
                            first_user,
                            first_user.language.get(
                                Token.TODAYS_WINNER_WITHOUT_EMAIL),
                            parse_mode=ParseMode.HTML)
                    else:
                        send_message_to_user(
                            mwexpress_bot.bot,
                            first_user,
                            first_user.language.get(
                                Token.TODAYS_WINNER_WITH_EMAIL) %
                            first_user.email,
                            parse_mode=ParseMode.HTML)
                    mwexpress_bot.bot.send_message(
                        mwexpress_config.moderator,
                        f"Todays champion is: {first_user.username}")
            except Exception as ex:
                mwelog.exception(ex)
Example #16
0
def start(update: Update, context: CallbackContext):
    user = get_user_from_update(update)

    mwelog.info("User {user_name} started using Mwexpress",
                user_name=user.username,
                user_id=user.id)

    clear_state(context)

    context.bot.send_sticker(update.effective_chat.id, TIPS_FEDORA_STICKER)
    reply_to(user, update, user.language.get(Token.WELCOME_MESSAGE_1),
             Keyboard.remove())
    time.sleep(2)
    reply_to(user, update, user.language.get(Token.WELCOME_MESSAGE_2),
             Keyboard.remove())
    time.sleep(5)
    reply_to(user, update, user.language.get(Token.WELCOME_MESSAGE_3),
             Keyboard.remove())
    time.sleep(3)
    reply_to(user, update, user.language.get(Token.WELCOME_MESSAGE_4),
             Keyboard.remove())
    time.sleep(2)
    reply_to(user, update, user.language.get(Token.WELCOME_MESSAGE_5),
             Keyboard.remove())
    time.sleep(5)
    reply_to(user, update, user.language.get(Token.WELCOME_MESSAGE_6),
             Keyboard.remove())
    time.sleep(10)
    update.message.reply_text(text=user.language.get(Token.WELCOME_MESSAGE_7),
                              parse_mode=ParseMode.HTML,
                              reply_markup=Keyboard.remove())
    time.sleep(5)
    context.bot.send_photo(user.id, open("assets/keyboard_button.png", "rb"))
    time.sleep(0.5)
    reply_to(user, update, user.language.get(Token.WELCOME_MESSAGE_8))
    time.sleep(5)
    reply_to(user, update, user.language.get(Token.DISCLAIMER),
             Keyboard.main(user))
Example #17
0
def language_update_handler(user: User, update: Update,
                            context: CallbackContext) -> None:
    if update.message.text == user.language.get(Token.LANGUAGE_ENGLISH):
        change_user_language(user, Language.ENGLISH)
        clear_state(context)
        reply_to(user, update,
                 user.language.get(Token.LANGUAGE_CHANGE_SUCCESSFUL),
                 Keyboard.main(user))
    elif update.message.text == user.language.get(Token.LANGUAGE_TURKISH):
        change_user_language(user, Language.TURKISH)
        clear_state(context)
        reply_to(user, update,
                 user.language.get(Token.LANGUAGE_CHANGE_SUCCESSFUL),
                 Keyboard.main(user))
    else:
        mwelog.info(
            "User {user_name} entered wrong value ({message}) for language change.",
            user_name=user.username,
            user_id=user.id,
            message=update.message.text)
        reply_to(user, update,
                 user.language.get(Token.PLEASE_SELECT_VALID_LANGUAGE),
                 Keyboard.language_selection(user.language))
Example #18
0
def message(update: Update, context: CallbackContext):
    user = get_user_from_update(update)
    try:
        mwelog.info("New message from {user_name}: {message}",
                    user_name=user.username,
                    message=update.message.text)

        if user.banned:
            update.message.reply_text(
                user.language.get(Token.USER_IS_BANNED_MESSAGE))
            return

        if update.message.text.startswith("/flag"):
            flag_submission(user, int(update.message.text.replace("/flag",
                                                                  "")),
                            context)
            return
        if update.message.text.startswith("/ban"):
            ban_user(user, int(update.message.text.replace("/ban", "")),
                     context)
            return

        if mwexpress_config.game_stopped:
            update.message.reply_sticker(COFFEE_STICKER)
            update.message.reply_text(
                user.language.get(Token.GAME_TEMPORARILY_STOPPED))
            update.message.reply_text(user.language.get(Token.SURVEY_MESSAGE))
            return

        if get_state(context) != State.NONE:
            state = get_state(context)
            mwelog.info("Current state for {user_name}: {state}",
                        user_name=user.username,
                        state=str(state))
            if state == State.SUBMISSION:
                main_submit_handler(user, update, context)
            elif state == State.CHANGING_LANGUAGE:
                language_update_handler(user, update, context)
            elif state == State.REVIEWING:
                main_review_handler(user, update, context)
            elif state == State.ADDING_EMAIL:
                main_email_handler(user, update, context)
        else:
            if update.message.text == user.language.get(Token.TODAYS_MWE):
                todays_mwe_handler(user, update)
            elif update.message.text == user.language.get(Token.SUBMIT):
                main_submit_handler(user, update, context)
            elif update.message.text == user.language.get(
                    Token.CHANGE_LANGUAGE):
                language_change_handler(user, update, context)
            elif update.message.text == user.language.get(Token.HELP):
                help_handler(user, update, context)
            elif update.message.text == user.language.get(Token.REVIEW):
                main_review_handler(user, update, context)
            elif update.message.text == user.language.get(Token.FEEDBACK):
                feedback_handler(user, update, context)
            elif update.message.text == user.language.get(
                    Token.SHOW_SCOREBOARD):
                scoreboard_handler(user, update, context)
            elif update.message.text == user.language.get(Token.ACHIEVEMENTS):
                achievements_handler(user, update, context)
            elif update.message.text == user.language.get(Token.ADD_EMAIL):
                main_email_handler(user, update, context)
            elif submission_contains_todays_mwe(user, update.message.text):
                context.user_data["sub_state"] = "typing_example"
                main_submit_handler(user, update, context)
            else:
                update.message.reply_text(user.language.get(
                    Token.ENTER_VALID_COMMAND),
                                          parse_mode=ParseMode.MARKDOWN,
                                          reply_markup=Keyboard.main(user))
                context.bot.send_photo(
                    user.id, open("assets/keyboard_button.png", "rb"))
                update.message.reply_text(user.language.get(
                    Token.WELCOME_MESSAGE_8),
                                          parse_mode=ParseMode.MARKDOWN,
                                          reply_markup=Keyboard.main(user))

    except Exception as ex:
        clear_state(context)
        unmute_user(user.id)
        _safe_delete_context_data(context, "sub_state")
        _safe_delete_context_data(context, "parsed")
        _safe_delete_context_data(context, "submission")
        mwelog.error(
            f"erroneous message: {user.username}: {update.message.text}")
        mwelog.exception(str(ex))
        update.message.reply_text(user.language.get(Token.ERROR_OCCURRED),
                                  reply_markup=Keyboard.main(user))
Example #19
0
 def listen(self):
     mwelog.info("Listening Telegram for connections...")
     self.updater.start_polling()
Example #20
0
def stats(update: Update, context: CallbackContext):
    user = get_user_from_update(update)
    mwelog.info(f"Stats requested by {user.username}")

    today = datetime.now().date()

    if len(context.args) == 3:
        day = int(context.args[0])
        month = int(context.args[1])
        year = int(context.args[2])
        today = datetime(year, month, day).date()

    update.message.reply_text(f'Stats for {today.strftime("%A, %B %d, %Y")}')

    session = database.get_session()
    all_users_count = session.query(User).filter(
        func.Date(User.created) <= today).count()
    new_users = session.query(User).filter(
        func.Date(User.created) == today).all()
    update.message.reply_text(
        f'{all_users_count} users (+{len(new_users)} new)')
    if len(new_users) > 0:
        update.message.reply_text(
            f'New users: {", ".join([x.username for x in new_users])}')

    all_submissions_count = session.query(Submission).filter(
        func.Date(Submission.created) <= today).count()
    new_submissions_count = session.query(Submission).filter(
        func.Date(Submission.created) == today).count()
    update.message.reply_text(
        f'{all_submissions_count} submissions (+{new_submissions_count} new)')

    all_reviews_count = session.query(Review).filter(
        func.Date(Review.created) <= today).count()
    new_reviews_count = session.query(Review).filter(
        func.Date(Review.created) == today).count()
    update.message.reply_text(
        f'{all_reviews_count} reviews (+{new_reviews_count} new)')

    all_subs = session.query(Submission).all()
    all_subs_today = session.query(Submission).filter(
        func.Date(Submission.created) == today).all()
    review_count_average = round(
        statistics.mean([x.review_count for x in all_subs]), 2)
    review_count_average_today = 0.0
    if len(all_subs_today) > 0:
        review_count_average_today = round(
            statistics.mean([x.review_count for x in all_subs_today]), 2)
    update.message.reply_text(
        f'Review count average: {review_count_average}({review_count_average_today} today)'
    )

    all_reviews_today = session.query(Review).filter(
        func.Date(Review.created) == today).all()
    all_submitted_users_today = set([x.user.id for x in all_subs_today])
    all_reviewed_users_today = set([x.user.id for x in all_reviews_today])

    update.message.reply_text(
        f'Users who only submitted: {len([x for x in all_submitted_users_today if x not in all_reviewed_users_today])}'
    )
    update.message.reply_text(
        f'Users who only reviewed: {len([x for x in all_reviewed_users_today if x not in all_submitted_users_today])}'
    )
    update.message.reply_text(
        f'Users who both submitted and reviewed: {len([x for x in all_submitted_users_today if x in all_reviewed_users_today])}'
    )

    positive_together_count = session.query(Submission)\
        .filter(Submission.category == SubmissionCategory.POSITIVE_TOGETHER)\
        .filter(func.Date(Submission.created) == today)\
        .count()
    positive_separated_count = session.query(Submission)\
        .filter(Submission.category == SubmissionCategory.POSITIVE_SEPARATED)\
        .filter(func.Date(Submission.created) == today)\
        .count()
    negative_together_count = session.query(Submission)\
        .filter(Submission.category == SubmissionCategory.NEGATIVE_TOGETHER)\
        .filter(func.Date(Submission.created) == today)\
        .count()
    negative_separated_count = session.query(Submission)\
        .filter(Submission.category == SubmissionCategory.NEGATIVE_SEPARATED)\
        .filter(func.Date(Submission.created) == today)\
        .count()
    update.message.reply_text(
        f"Submission categories:\nPositive together: {positive_together_count}\n"
        f"Positive separated: {positive_separated_count}\n"
        f"Negative together: {negative_together_count}\n"
        f"Negative separated: {negative_separated_count}")
Example #21
0
from bot.main import mwexpress_bot
from log import mwelog
from cron import schedule_jobs, run_scheduled_jobs
from initial_data import load_initial_data

load_initial_data()

mwelog.info("Starting MWExpress...")

mwexpress_bot.listen()

schedule_jobs()
run_scheduled_jobs()
Example #22
0
def reply_html(user: User, update: Update, message: str,
               reply_markup: Optional[ReplyMarkup] = None) -> None:
    mwelog.info("Bot replied to {user_name} with: {message}",
                user_name=user.username, user_id=user.id, message=message)
    update.message.reply_text(text=message, parse_mode=ParseMode.HTML,
                              reply_markup=reply_markup)
Example #23
0
def clear_state(context: CallbackContext) -> None:
    set_state(context, State.NONE)
    mwelog.info("State cleared")
Example #24
0
def set_state(context: CallbackContext, state: State) -> None:
    context.user_data["state"] = state
    mwelog.info("State set to: {state}", state=str(state))
Example #25
0
def sticker(update: Update, context: CallbackContext):
    mwelog.info("Got sticker: {sticker_id}",
                sticker_id=update.message.sticker.file_id)
    context.bot.send_sticker(update.effective_chat.id,
                             update.message.sticker.file_id)