예제 #1
0
    def __init__(self):
        super().__init__()
        gettext = Texts()
        self.text1 = gettext.text1()
        self.text1_2 = gettext.text1_2()
        self.text1_3 = gettext.text1_3()
        self.text1_4 = gettext.text1_4()
        self.text2 = gettext.text2()
        self.text3 = gettext.text3()

        FrontEnd.main(self)
def newtextcontrol():
    if request.method == "POST":
        title = request.form['title']
        text = request.form['text']
        user = session['username']
        _id = uuid.uuid4().hex

        new_post = Texts(user, title, text, _id)
        new_post.save_to_db()

        return redirect(url_for("dashboardmon"))
    else:
        return render_template("controlbasiceditor.html")
def newtext():
    if request.method == "POST":
        title = request.form['title']
        text = request.form['content']
        user = session['username']
        _id = uuid.uuid4().hex

        new_post = Texts(user, title, text, _id)
        new_post.save_to_db()

        text_summary = Grammar.summary(text)
        DB.text_version(user_id=session['username'], date=datetime.datetime.utcnow(), text=text, status="new")

        return render_template("summary.html", text_summary=text_summary, text_id=_id)
    else:
        return render_template("basiceditor.html")
예제 #4
0
        def get_texts(cls, path, fargs, languages=None):
            path = path / 'texts'
            if path.is_dir():
                texts, errors = Texts.load(
                    path,
                    languages=languages,
                    default_content=cls.get_txt_args(fargs))

                if not errors.is_empty():
                    print(errors)

            else:
                texts = Texts(languages=languages,
                              default_content=cls.get_txt_args(fargs))

            return texts
예제 #5
0
class Melissa:
    """Main class"""

    logger = logging.getLogger(__name__)
    chats = dict()
    parameters = dict()
    channel = int(Config.TELEGRAM_CHANNEL)
    admins = [int(user) for user in Config.TELEGRAM_ADMINS.split(',')]
    games = {}
    try:
        texter = Texts()
    except FileNotFoundError as e:
        logger.critical('Cannot find language files')
        exit(errno.ENOENT)
    else:
        logger.info('Language files loaded')

    def __init__(self):

        logging.basicConfig(
            format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
            filename=Config.LOG_FILE_NAME,
            level=Config.LOG_LEVEL)
        consoleHandler = logging.StreamHandler()
        self.logger.addHandler(consoleHandler)

        try:
            self.db_engine = sqlalchemy.create_engine(
                Config.SQLALCHEMY_DB_CONN)
            self.connection = self.db_engine.connect()
            self.metadata = sqlalchemy.MetaData()
            Session = sessionmaker(self.db_engine)
            self.session = Session()
        except Exception as e:  # TODO specify exceptions
            self.logger.critical(e)
            exit(errno.ECONNREFUSED)
        else:
            self.logger.warning('Connection to database established')

        try:
            self.parameters['adv_minutes'] = self.session.query(
                models.Parameter).get('adv_minutes').value
            self.parameters['adv_questions'] = self.session.query(
                models.Parameter).get('adv_questions').value
            self.parameters['base_points'] = self.session.query(
                models.Parameter).get('base_points').value
            self.parameters['current_broadcast'] = self.session.query(
                models.Parameter).get('current_broadcast').value
            self.parameters['google_points'] = self.session.query(
                models.Parameter).get('google_points').value
            self.parameters['hint_pause'] = self.session.query(
                models.Parameter).get('hint_pause').value
            self.parameters['max_time'] = self.session.query(
                models.Parameter).get('max_time').value
            self.parameters['min_members'] = self.session.query(
                models.Parameter).get('min_members').value
            self.parameters['next_pause'] = self.session.query(
                models.Parameter).get('next_pause').value
            self.parameters['series_max'] = self.session.query(
                models.Parameter).get('series_max').value
            self.parameters['top_limit'] = self.session.query(
                models.Parameter).get('top_limit').value
        except Exception as e:  # TODO specify exceptions
            self.logger.error(e)
            self.parameters = Config.DEFAULT_PARAMETERS
            self.logger.warning('Cannot load parameters. Defaults used.')

        # TODO improvement: add different game types later
        from games import TextQuiz
        game = TextQuiz(self.session)
        self.games[game.name] = game

        for chat in self.session.query(models.Chat).all():
            self.chats[chat.id] = Chat(c_id=chat.id,
                                       u_id=chat.u_id,
                                       q_id=chat.q_id,
                                       is_on=chat.is_on,
                                       lang=chat.lang,
                                       game=self.games[chat.game],
                                       parameters=self.parameters)
        for user in self.session.query(models.User).all():
            self.chats[user.chat_id].users[user.id] = User(
                u_id=user.id,
                name=user.user_name,
                correct_answers=user.correct_answers,
                points=user.points)

        try:
            updater = Updater(Config.TELEGRAM_TOKEN, use_context=True)
        except Exception as e:
            self.logger.critical(e)
            exit(errno.ECONNREFUSED)
        else:
            self.logger.warning('Connection to Telegram established')

            dp = updater.dispatcher

            dp.add_handler(CommandHandler('start', self.cmd_start))
            dp.add_handler(CommandHandler('play', self.cmd_play))
            dp.add_handler(CommandHandler('stop', self.cmd_stop))
            dp.add_handler(CommandHandler('hint', self.cmd_hint))
            dp.add_handler(CommandHandler('score', self.cmd_score))
            dp.add_handler(CommandHandler('ask', self.cmd_ask))
            dp.add_handler(CommandHandler('lang', self.cmd_lang))
            dp.add_handler(CommandHandler('next', self.cmd_next))
            dp.add_handler(
                CommandHandler('setparameter', self.cmd_setparameter))
            # dp.add_handler(CommandHandler('stop_bot', self.cmd_stop_bot))
            #
            dp.add_handler(
                MessageHandler(Filters.regex('^(/top[\d]+)$'), self.cmd_top))
            dp.add_handler(MessageHandler(Filters.text, self.message))

            dp.add_error_handler(self.errors)

            self.logger.warning('Melissa Quiz started... ')

            updater.start_polling()

            # Run the bot until you press Ctrl-C or the process receives SIGINT,
            # SIGTERM or SIGABRT. This should be used most of the time, since
            # start_polling() is non-blocking and will stop the bot gracefully.
            updater.idle()

    def cmd_start(self, update, context):
        """/start command"""

        if update.effective_user.is_bot is True:
            return

        self.logger.info(update.message.text + ' from user ' +
                         str(update.effective_user.id))

        greetings = self.texter.get_text(text_id='greetings',
                                         lang=Config.DEFAULT_LANGUAGE)

        greetings = greetings.format(
            min_members=self.parameters['min_members'],
            max_time=self.parameters['max_time'],
            hint_pause=self.parameters['hint_pause'])
        context.bot.send_message(chat_id=update.effective_chat.id,
                                 text=greetings,
                                 parse_mode="HTML",
                                 disable_web_page_preview=True)

    def cmd_setparameter(self, update, context):
        """/setparameter command"""

        if update.effective_user.is_bot is True:
            return

        if update.effective_user.id not in self.admins:
            return

        try:
            parameter, value = update.message.text.split(' ', 3)[1:3]
            self.parameters[parameter] = value
        except Exception as e:  # TODO specify exceptions
            update.message.reply_text(
                self.texter.get_text('set_parameter_format',
                                     lang=Config.DEFAULT_LANGUAGE))
        out_text = self.texter.get_text('set_parameter_head')
        for p in self.parameters:
            out_text += self.texter.get_text('set_parameter_text', Config.DEFAULT_LANGUAGE) \
                .format(parameter=p,
                        value=self.parameters[p])
        update.message.reply_text(out_text)

    def cmd_score(self, update, context):
        """/score command"""

        if update.effective_user.is_bot is True:
            return

        self.logger.info(update.message.text + ' from user ' +
                         str(update.effective_user.id))

        if update.effective_chat.id in self.chats \
                and update.effective_user.id in self.chats[update.effective_chat.id].users:
            chat = self.chats[update.effective_chat.id]
            out_text = self.texter.get_text('score_head',
                                            lang=chat.lang) \
                .format(user_name=update.effective_user.name)
            out_text += self.texter.get_text(
                'score_text', lang=chat.lang).format(
                    points=self.chats[update.effective_chat.id].users[
                        update.effective_user.id].get_points())
            # TODO implement: return rating place as well
        else:
            out_text = self.texter.get_text('score_notagamer',
                                            lang=Config.DEFAULT_LANGUAGE)
        update.message.reply_text(out_text)

    def cmd_top(self, update, context):
        """/top command"""

        if update.effective_user.is_bot is True:
            return

        self.logger.info(update.message.text + ' from user ' +
                         str(update.effective_user.id))

        try:
            top_qty = int(update.message.text[4:])
        except Exception as e:  # TODO specify exceptions
            top_qty = 10
            self.logger.info('Cannot recognize TOP N from ' +
                             update.message.text + str(e))

        if top_qty > self.parameters['top_limit']:
            top_qty = self.parameters['top_limit']

        if update.effective_chat.id not in self.chats:
            return

        chat = self.chats[update.effective_chat.id]
        out_text = self.texter.get_text('top_head', lang=chat.lang) \
            .format(top_qty=top_qty)

        players = self.session.query(models.User).order_by(
            models.User.points.desc()).limit(top_qty)

        # TODO fix: problem with stored emoji (utf8mb4)
        for player in players:
            out_text += self.texter.get_text('top_line', lang=chat.lang) \
                .format(bullet='•',
                        user=player.user_name,
                        points=player.points)

        context.bot.send_message(chat_id=update.effective_chat.id,
                                 text=out_text)

    def cmd_play(self, update, context):
        """/play command"""
        if update.effective_user.is_bot is True:
            return

        self.logger.info(update.message.text + ' from user ' +
                         str(update.effective_user.id))

        if update.effective_chat.get_member_count(
        ) < self.parameters['min_members']:
            out_text = self.texter.get_text('min_members_group_play',
                                            lang=Config.DEFAULT_LANGUAGE)
            context.bot.send_message(
                chat_id=update.effective_chat.id,
                text=out_text.format(
                    min_members=self.parameters['min_members']),
                parse_mode='HTML')
            return
        if update.effective_chat.id not in self.chats:
            # TODO improvement: add different game types later
            game = self.games['textquiz']
            chat = Chat(c_id=update.effective_chat.id,
                        u_id=update.effective_user.id,
                        game=game,
                        parameters=self.parameters,
                        is_on=True,
                        lang=Config.DEFAULT_LANGUAGE)
            chat.next_question()
            self.chats[update.effective_chat.id] = chat
        else:
            chat = self.chats[update.effective_chat.id]
            chat.is_on = True
        self.session.merge(
            models.Chat(id=chat.id,
                        u_id=chat.u_id,
                        q_id=chat.q_id,
                        is_on=chat.is_on,
                        lang=chat.lang,
                        game=chat.game.name))
        self.session.commit()
        if update.effective_user.id not in chat.users:
            self.new_player(update)
        self.cmd_ask(update, context)

    def cmd_stop(self, update, context):
        """/stop command"""
        if update.effective_user.is_bot is True:
            return

        self.logger.info(update.message.text + ' from user ' +
                         str(update.effective_user.id))

        if update.effective_chat.id not in self.chats \
           or self.chats[update.effective_chat.id].is_on is False:
            return

        chat = self.chats[update.effective_chat.id]
        chat.is_on = False
        self.session.merge(
            models.Chat(id=chat.id,
                        u_id=chat.u_id,
                        q_id=chat.q_id,
                        is_on=chat.is_on,
                        lang=Config.DEFAULT_LANGUAGE,
                        game=chat.game.name))
        self.session.commit()

        stop_message = self.texter.get_text(text_id='game_stopped',
                                            lang=chat.lang)
        context.bot.send_message(chat_id=update.effective_chat.id,
                                 text=stop_message,
                                 parse_mode="HTML",
                                 disable_web_page_preview=True)

    def cmd_lang(self, update, context):
        """/lang command"""
        if update.effective_user.is_bot is True:
            return

        self.logger.info(update.message.text + ' from user ' +
                         str(update.effective_user.id))

        if update.effective_chat.id not in self.chats \
           or self.chats[update.effective_chat.id].is_on is False:
            return

        chat = self.chats[update.effective_chat.id]
        if chat.lang == 'en':
            chat.lang = 'ru'
        else:
            chat.lang = 'en'
        self.session.merge(
            models.Chat(id=chat.id,
                        u_id=chat.u_id,
                        q_id=chat.q_id,
                        is_on=chat.is_on,
                        lang=chat.lang,
                        game=chat.game.name))
        self.session.commit()

        lang_message = self.texter.get_text(
            text_id='lang_set', lang=chat.lang).format(lang=chat.lang)
        context.bot.send_message(chat_id=update.effective_chat.id,
                                 text=lang_message,
                                 parse_mode="HTML",
                                 disable_web_page_preview=True)

    def cmd_hint(self, update, context):
        """/hint command"""

        if update.effective_user.is_bot is True:
            return

        if update.effective_chat.id not in self.chats:
            return

        self.logger.info(update.message.text + ' from user ' +
                         str(update.effective_user.id))

        chat = self.chats[update.effective_chat.id]
        if chat.is_on is False:
            return

        hint_result = chat.do_hint()

        if hint_result == 'hint_ok':
            sym = self.texter.get_text('hint_symbol', lang=chat.lang)
            sep = self.texter.get_text('hint_separator', lang=chat.lang)
            out_text = self.texter.get_text('hint_text', lang=chat.lang) \
                .format(hint_text=chat.get_hint_text(sym, sep))
            context.bot.send_message(chat_id=update.effective_chat.id,
                                     text=out_text,
                                     parse_mode='HTML')
        elif hint_result in ['whole_word_open', 'max_time_exceed']:
            chat.next_question()
            self.session.merge(
                models.Chat(id=chat.id,
                            u_id=chat.u_id,
                            q_id=chat.q_id,
                            is_on=chat.is_on,
                            lang=chat.lang,
                            game=chat.game.name)
            )  # TODO improvement: add different game types later
            self.session.commit()
            out_text = self.texter.get_text('nobody_could', lang=chat.lang)
            context.bot.send_message(chat_id=update.effective_chat.id,
                                     text=out_text,
                                     parse_mode='HTML')
            out_text = self.texter.get_text('ask_question', lang=chat.lang) \
                .format(question=chat.get_question())
            context.bot.send_message(chat_id=update.effective_chat.id,
                                     text=out_text,
                                     parse_mode='HTML')
        elif hint_result == 'hint_pause_not_spent':
            pass
        else:
            self.logger.error('Hint error: ' + hint_result)

    def cmd_next(self, update, context):
        """/next command"""

        if update.effective_user.is_bot is True:
            return

        if update.effective_chat.id not in self.chats:
            return

        self.logger.info(update.message.text + ' from user ' +
                         str(update.effective_user.id))

        chat = self.chats[update.effective_chat.id]
        if chat.is_on is False:
            return

        if chat.next_question():
            self.session.merge(
                models.Chat(id=chat.id,
                            u_id=chat.u_id,
                            q_id=chat.q_id,
                            is_on=chat.is_on,
                            lang=chat.lang,
                            game=chat.game.name))
            self.session.commit()
            self.cmd_ask(update, context)
        else:
            out_text = self.texter.get_text('lets_think_more', lang=chat.lang) \
                .format(question=chat.get_question())
            context.bot.send_message(chat_id=chat.id,
                                     text=out_text,
                                     parse_mode='HTML')

    def cmd_ask(self, update, context):
        """/ask command"""

        if update.effective_user.is_bot is True:
            return

        if update.effective_chat.id not in self.chats:
            return

        self.logger.info(update.message.text + ' from user ' +
                         str(update.effective_user.id))

        chat = self.chats[update.effective_chat.id]
        if chat.is_on is False:
            return

        if self.parameters['current_broadcast'] and chat.need_broadcast():
            context.bot.forward_message(chat.id, self.channel,
                                        self.parameters['current_broadcast'])
        out_text = self.texter.get_text('ask_question', lang=chat.lang) \
            .format(question=chat.get_question())
        context.bot.send_message(chat_id=chat.id,
                                 text=out_text,
                                 parse_mode='HTML')

    def message(self, update, context):
        """message in chat"""

        # new message in bot channel
        if update.effective_chat.id == self.channel and update.channel_post.message_id:
            self.logger.info(update.channel_post.text + ' from channel ' +
                             str(update.effective_chat.id))
            for user in self.admins:
                context.bot.forward_message(user, self.channel,
                                            update.channel_post.message_id)
                out_text = self.texter.get_text('broadcast_newpost', lang=Config.DEFAULT_LANGUAGE) \
                    .format(message_id=str(update.channel_post.message_id))
                context.bot.send_message(chat_id=user,
                                         text=out_text,
                                         parse_mode='HTML')
            return

        # message in game chat
        if update.effective_user.is_bot is True:
            return

        if update.effective_chat.id not in self.chats:
            return

        chat = self.chats[update.effective_chat.id]
        if chat.is_on is False:
            return

        if update.effective_user.id not in chat.users:
            self.new_player(update)
        user = chat.users[update.effective_user.id]

        if chat.max_time_exceed():
            context.bot.send_message(chat_id=chat.id,
                                     text=self.texter.get_text('nobody_could',
                                                               lang=chat.lang),
                                     parse_mode='HTML')
            chat.next_question()
            self.session.merge(
                models.Chat(id=chat.id,
                            u_id=chat.u_id,
                            q_id=chat.q_id,
                            is_on=chat.is_on,
                            lang=chat.lang,
                            game=chat.game.name)
            )  # TODO improvement: add different game types later
            self.session.commit()
            out_text = self.texter.get_text('ask_question', lang=chat.lang) \
                .format(question=chat.get_question())
            context.bot.send_message(chat_id=chat.id,
                                     text=out_text,
                                     parse_mode='HTML')
            return

        if chat.game.answer_is_correct(chat.q_id, update.message.text) \
           and chat.is_on and chat.got_correct_answer is False:
            # turn off game, we don't want to get more than one winner
            chat.got_correct_answer = True

            # calculate points for correction answer
            points = chat.parameters['base_points'] \
                - chat.hint.count(True) / len(chat.hint) \
                * chat.parameters['base_points']
            multiplied_points = points = int(round(points, 0))
            if points < 1:
                points = 1
            combo_str_list = []

            # double points if it was quick answer
            if chat.check_speed():
                multiplier = 2
                points = points * multiplier
                combo_str_list.append(
                    self.texter.get_text('quick_answer', lang=chat.lang) \
                        .format(multiplier=multiplier))

            # count correct answer in chat and user
            chat.count_correct_answer(user)

            # if user exceeded limit count of answers in series
            if chat.answer_count > chat.parameters['series_max']:
                points = chat.parameters['google_points']
                combo_str_list.append(
                    self.texter.get_text('was_googled', lang=chat.lang))
            else:
                # series is going, multiply points
                multiplier = chat.answer_count
                multiplied_points = points * multiplier
                combo_str_list.append(
                    self.texter.get_text('series_answer', lang=chat.lang) \
                        .format(multiplier=multiplier))

            user.add_points(multiplied_points)
            self.session.merge(
                models.User(chat_id=chat.id,
                            id=user.id,
                            correct_answers=user.correct_answers,
                            points=user.points,
                            user_name=user.name))
            self.session.commit()
            out_text = self.texter.get_text('get_points', lang=chat.lang) \
                .format(username=user.get_name(),
                        points=str(points))
            out_text += '\n' + '\n'.join(combo_str_list)
            out_text += '\n' + self.texter.get_text('result_points', lang=chat.lang) \
                .format(points=str(multiplied_points))

            # congratulate user
            context.bot.send_message(chat_id=chat.id,
                                     text=out_text,
                                     parse_mode='HTML')

            # go to the next question
            chat.next_question()
            self.session.merge(
                models.Chat(id=chat.id,
                            u_id=chat.u_id,
                            q_id=chat.q_id,
                            is_on=chat.is_on,
                            lang=chat.lang))
            self.session.commit()

            out_text = self.texter.get_text('ask_question', lang=chat.lang) \
                .format(question=chat.get_question())
            context.bot.send_message(chat_id=chat.id,
                                     text=out_text,
                                     parse_mode='HTML')

        # wrong answer and bad words in it
        elif self.texter.check_bad(update.message.text):
            update.message.reply_text(self.texter.get_joke())

    def new_player(self, update):
        chat = self.chats[update.effective_chat.id]
        try:
            # getting user from database
            result = self.session.query(models.User).\
                filter(models.User.id == update.effective_user.id and models.User.chat_id == chat.id)
            user = User(u_id=result[0].id,
                        name=result[0].user_name,
                        correct_answers=result[0].correct_answers,
                        points=result[0].points)
        except Exception as e:
            # new user
            self.logger.debug(str(e))
            user = User(u_id=update.effective_user.id,
                        name=update.effective_user.username)
            self.session.merge(
                models.User(chat_id=chat.id,
                            id=user.id,
                            points=user.points,
                            user_name=user.name,
                            correct_answers=user.correct_answers))
            self.session.commit()
        chat.new_user(user)

    def errors(self, update, context):
        """Error handler"""
        self.logger.warning('Update "%s" caused error "%s"' %
                            (update, context.error))