Example #1
0
    def get_user_position(cls, user_id, cid, date):
        position = -1
        msg_count = 0
        last_monday = get_current_monday(
        ) if date is None else get_date_monday(date)

        try:
            with session_scope() as db:
                # noinspection PyUnresolvedReferences
                q = db.query(UserStatDB, UserDB) \
                    .filter(UserStatDB.stats_monday == last_monday) \
                    .filter(UserStatDB.uid == UserDB.uid) \
                    .filter(UserStatDB.cid == cid) \
                    .filter(UserStatDB.all_messages_count > 0) \
                    .order_by(UserStatDB.all_messages_count.desc()) \
                    .all()
                q = [(UserStat.copy(userstat), User.copy(user))
                     for userstat, user in q]
            if q:
                position = 0
                for userstat, user in q:
                    position += 1
                    if userstat.uid == user_id:
                        msg_count = userstat.all_messages_count
                        break
        except Exception as e:
            logger.error(e)
        return {'position': position, 'msg_count': msg_count}
Example #2
0
 def get_stats_unlimited(cls, cid, date=None):
     """
     Как get_stats, но с полным показом страсти, без игнорирования
     """
     monday = get_current_monday() if date is None else get_date_monday(
         date)
     db = cls.db_helper.get_db(monday, cid)
     return {
         'to': sort_dict(db['to']),
         'from': sort_dict(db['from']),
         'pair': sort_dict(db['pair'])
     }
Example #3
0
 def get_stats(cls, cid, date=None):
     monday = get_current_monday() if date is None else get_date_monday(
         date)
     db = cls.db_helper.get_db(monday, cid)
     ignore = CONFIG.get('replylove__ignore', [])
     return {
         'to':
         sort_dict(cls.__remove_uids(db['to'], ignore))[:3],
         'from':
         sort_dict(cls.__remove_uids(db['from'], ignore))[:3],
         'pair':
         sort_dict(
             cls.__ignore_pairs(cid, cls.__remove_uids(db['pair'],
                                                       ignore)))[:10]
     }
Example #4
0
def send_topmat(bot: telegram.Bot,
                send_to_cid: int,
                stats_from_cid: int,
                date=None) -> None:
    monday = get_current_monday() if date is None else get_date_monday(date)
    stats = UserStat.get_chat_stats(stats_from_cid, date)
    words = get_words_from_cache(monday, stats_from_cid)
    users_msg_stats = get_mat_users_msg_stats(stats)
    msg = format_msg(
        'Стата по мату', {
            'header_stats': get_header_stats(stats),
            'users_msg_stats': users_msg_stats,
            'users_words_stats': get_mat_users_words_stats(stats),
            'words_stats': get_words_stats(words),
        })
    set_top_mater(stats_from_cid, users_msg_stats)
    bot.send_message(send_to_cid, msg, parse_mode=telegram.ParseMode.HTML)
Example #5
0
    def dump(cls, cid) -> None:
        current_dir = os.getcwd()
        tmp_dir = f'{current_dir}/tmp/reply_top/{cid}'
        os.makedirs(os.path.dirname(f'{tmp_dir}/'), exist_ok=True)

        yesterday = get_yesterday()
        yesterday_str = yesterday.strftime('%Y%m%d')
        monday = get_date_monday(yesterday)
        monday_str = monday.strftime('%Y%m%d')

        # недельная страсть будет каждый день нарастать
        cls.__dump(f'{tmp_dir}/{monday_str}_week_{yesterday_str}.json',
                   ReplyTop.db_helper.get_db(monday, cid))

        # ежедневная страсть каждый день с нуля начинает
        cls.__dump(f'{tmp_dir}/{monday_str}_day_{yesterday_str}.json',
                   ReplyTopDaily.db_helper.get_db(yesterday, cid))
Example #6
0
 def get_chat_stats(cls, cid, date=None):
     last_monday = get_current_monday(
     ) if date is None else get_date_monday(date)
     try:
         with session_scope() as db:
             # noinspection PyUnresolvedReferences
             q = db.query(UserStatDB, UserDB) \
                 .filter(UserStatDB.stats_monday == last_monday) \
                 .filter(UserStatDB.uid == UserDB.uid) \
                 .filter(UserStatDB.cid == cid) \
                 .filter(UserStatDB.all_messages_count > 0) \
                 .order_by(UserStatDB.all_messages_count.desc()) \
                 .all()
         return [(UserStat.copy(userstat), User.copy(user))
                 for userstat, user in q]
     except Exception:
         return []
Example #7
0
    def get_top_kroshka(cls, cid, date=None):
        """
        :rtype: User
        """
        last_monday = get_current_monday(
        ) if date is None else get_date_monday(date)
        try:
            with session_scope() as db:
                # noinspection PyUnresolvedReferences
                q = db.query(UserStatDB, UserDB) \
                    .filter(UserStatDB.stats_monday == last_monday) \
                    .filter(UserStatDB.uid == UserDB.uid) \
                    .filter(UserStatDB.cid == cid) \
                    .filter(or_(
                        UserStatDB.emoji_count > 0,
                        UserStatDB.stickers_count > 0,
                        UserStatDB.gifs_count > 0
                    )) \
                    .order_by(UserStatDB.emoji_count.desc()) \
                    .all()
                q = [(UserStat.copy(userstat), User.copy(user))
                     for userstat, user in q]
            if not q:
                return None
        except Exception as e:
            logger.error(e)
            return None

        # получаем соотношение количества эмодзи к сообщениям
        users_by_emoji = {}
        for user_stat, user in q:
            count = user_stat.all_messages_count
            # учитываем только тек, кто написал от 30 сообщений
            if count < 30 or user_stat.words_count < 500:
                continue
            users_by_emoji[user.uid] = user_stat.emoji_count / count

        if len(users_by_emoji) > 0:
            uid, _ = random.choice(sort_dict(users_by_emoji)[:10])
        else:
            _, user = random.choice(q)
            uid = user.uid
        user = User.get(uid)
        return user
Example #8
0
    def get_user_top_strast(
            cls,
            chat_id: int,
            user_id: int,
            date=None
    ) -> Tuple[Optional[User], Optional[User], Optional[User]]:
        def get_top(type: str, uid: int) -> Optional[User]:
            if type not in db:
                return None
            if uid not in db[type]:
                return None
            replylove__ignore = CONFIG.get('replylove__ignore', [])
            if uid in replylove__ignore:
                return None
            replylove__dragon_lovers = CONFIG.get('replylove__dragon_lovers',
                                                  [])
            if uid in replylove__dragon_lovers:
                return User(0, 0, 'drakon', '🐉')
            sorted: List[Tuple[int, int]] = sort_dict(db[type][uid])
            if len(sorted) == 0:
                return None
            replylove__ignore_pairs = CONFIG.get('replylove__ignore_pairs',
                                                 {}).get(str(chat_id),
                                                         {}).get(str(uid), [])
            for result_uid, count in sorted:
                if count < 5:
                    continue
                if uid == result_uid:
                    continue
                if result_uid in replylove__dragon_lovers:
                    continue
                if result_uid in replylove__ignore:
                    continue
                if result_uid in replylove__ignore_pairs:
                    continue
                return User.get(result_uid)
            return None

        def get_top_pair(uid: int) -> Optional[User]:
            replylove__dragon_lovers = CONFIG.get('replylove__dragon_lovers',
                                                  [])
            if uid in replylove__dragon_lovers:
                return User(0, 0, 'drakon', '🐉')
            replylove__ignore = CONFIG.get('replylove__ignore', [])
            replylove__ignore_pairs = CONFIG.get('replylove__ignore_pairs',
                                                 {}).get(str(chat_id),
                                                         {}).get(str(uid), [])
            pairs: List[Tuple[str, int]] = sort_dict(db['pair'])
            for pair, count in pairs:
                a_uid, b_uid = [get_int(x) for x in pair.split(',')]
                strast = None
                if a_uid is None or b_uid is None:
                    continue
                if count < 5:
                    continue
                if uid == a_uid and a_uid == b_uid:
                    continue
                if any(x in replylove__dragon_lovers for x in (a_uid, b_uid)):
                    continue
                if any(x in replylove__ignore for x in (uid, a_uid, b_uid)):
                    continue
                if any(x in replylove__ignore_pairs for x in (a_uid, b_uid)):
                    continue
                if uid == a_uid:
                    strast = User.get(b_uid)
                if uid == b_uid:
                    strast = User.get(a_uid)
                if strast:
                    return strast
            return None

        monday = get_current_monday() if date is None else get_date_monday(
            date)
        db = cls.db_helper.get_db(monday, chat_id)

        pair = get_top_pair(user_id)
        inbound = get_top('inbound', user_id)
        outbound = get_top('outbound', user_id)
        return pair, inbound, outbound
Example #9
0
 def add(cls, from_uid, to_uid, cid, date: Optional[datetime] = None):
     monday = get_current_monday() if date is None else get_date_monday(
         date)
     cls.db_helper.add(from_uid, to_uid, cid, monday)
     ReplyTopDaily.add(from_uid, to_uid, cid)
Example #10
0
    def get_chat(cls,
                 cid,
                 date=None,
                 fullstat=False,
                 salo=False,
                 tag_salo=False,
                 mat=False):
        if cid > 0:
            return {
                'users_count': 0,
                'top_chart': '',
                'msg_count': 0,
                'percent': 0
            }
        msg_count_percent = 100
        top_chart = ''
        uids = []
        last_monday = get_current_monday(
        ) if date is None else get_date_monday(date)
        all_msg_count = cls.__get_all_msg_count(last_monday, cid)

        q = []
        try:
            with session_scope() as db:
                # noinspection PyUnresolvedReferences
                q = db.query(UserStatDB, UserDB) \
                    .filter(UserStatDB.stats_monday == last_monday) \
                    .filter(UserStatDB.uid == UserDB.uid) \
                    .filter(UserStatDB.cid == cid) \
                    .filter(UserStatDB.all_messages_count > 0) \
                    .order_by(UserStatDB.all_messages_count.desc()) \
                    .all()
                q = [(UserStat.copy(userstat), User.copy(user))
                     for userstat, user in q]
        except Exception as e:
            logger.error(e)
        if len(q) == 0:
            return {
                'users_count': 0,
                'top_chart': '',
                'msg_count': 0,
                'percent': 0,
                'uids': []
            }

        user_position = 0
        asc_msg_count = 0
        if salo:
            q = q[::-1]

        magic_percent = 100
        q_all_length = len(q)  # if type(q) is list else len(q.all())
        if not salo and q_all_length > 25:
            magic_percent = 146

        for user_stat, user in q:
            count = user_stat.all_messages_count
            user_position += 1
            asc_msg_count += count
            raw_percent = count * magic_percent / all_msg_count
            percent = cls.number_format(raw_percent, 2)
            user_mat = '' if not mat else cls.__get_user_mat(user_stat)
            top_chart += f"<b>{user_position}. {user.fullname}</b> — <b>{count}</b> ({percent}%){user_mat}\n"
            uids.append(user.uid)
            if not fullstat and user_position >= CONFIG['top_users_num']:
                break
            if salo and count > 15:
                break

        if not salo:
            users_count = q_all_length
        else:
            users_count = user_position
            all_users: typing.List[ChatUser] = []
            try:
                all_users = ChatUserDB.get_all(cid)
            except Exception as e:
                logger.error(e)
            active_user_ids = [x.uid for _, x in q]
            silent_lines = []
            for chat_user in all_users:
                if chat_user.uid not in active_user_ids:
                    user = User.get(chat_user.uid)
                    if user is not None:
                        username_if_salo = ' @{}'.format(
                            user.username) if tag_salo else ''
                        silent_lines.append("<b>{}</b>{}\n".format(
                            user.fullname, username_if_salo))
            if len(silent_lines) > 0:
                top_chart += "\nСовсем молчуны:\n"
                top_chart += ''.join(silent_lines)
            else:
                top_chart += "\nСовсем молчунов нет 🙊\n"

        if not fullstat or salo:
            msg_count_percent = cls.number_format(
                asc_msg_count * 100 / all_msg_count, 2)
            all_msg_count = asc_msg_count

        return {
            'users_count': users_count,
            'top_chart': top_chart,
            'msg_count': all_msg_count,
            'percent': msg_count_percent,
            'uids': uids
        }
Example #11
0
    def me_format(cls, date, uid, cid):
        monday = get_date_monday(date)
        stat = cls.get(monday, uid, cid)
        if stat is None:
            return ''

        user = User.get(uid)

        # сообщения
        count_keys = {
            'all_messages_count': 'всего, всего, всего',
            'text_messages_count': 'сообщение, сообщения, сообщений',
            'text_messages_with_obscene_count':
            'сообщение с матом, сообщения с матом, сообщений с матом',
            'forwards_count': 'форвард, форварда, форвардов',
            # 'audios_count': 'аудио, аудио, аудио',
            # 'documents_count': 'файл, файла, файлов',
            'gifs_count': 'гифка, гифки, гифок',
            'photos_count': 'фотка, фотки, фоток',
            'stickers_count': 'стикер, стикера, стикеров',
            'videos_count': 'видео, видео, видео',
            'video_notes_count': 'кругляш, кругляша, кругляшей',
            'voices_count': 'войс, войса, войсов',
            'games_count': 'игра, игры, игр',
            'hashtags_count': 'хештег, хештега, хештегов',
            # 'bot_commands_count': 'команда боту, команды боту, команд боту',
            'urls_count': 'ссылка, ссылки, ссылок',
            'emails_count':
            'электронная почта, электронные почты, электронных почт',
            'emoji_count': 'эмодзи, эмодзи, эмодзи',
        }
        counts = []
        for key, plural_variants in count_keys.items():
            count = getattr(stat, key, None)
            if count is None or count == 0 or count == '':
                continue
            msg = pytils.numeral.get_plural(count, plural_variants)
            # if key == 'text_messages_count':
            #     msg = '{msg} ({words}, {chars})'.format(
            #         msg=msg,
            #         words=pytils.numeral.get_plural(getattr(stat, 'words_count', 0), 'слово, слова, слов'),
            #         chars=pytils.numeral.get_plural(getattr(stat, 'chars_wo_space_count', 0),
            #                                         'символ без пробелов, символа без пробелов, символов без пробелов'))
            if key == 'text_messages_with_obscene_count':
                text_messages_count = getattr(stat, 'text_messages_count', 0)
                msg_percent = round(count / text_messages_count * 100)
                obscene_words_count = getattr(stat, 'obscene_words_count', 0)
                words_count = getattr(stat, 'words_count', 0)
                words_percent = obscene_words_count / words_count * 100
                obscene_words_count_str = pytils.numeral.get_plural(
                    obscene_words_count,
                    'матерное слово, матерных слова, матерных слов')
                msg = f'{msg}, {msg_percent}% ({obscene_words_count_str}, {words_percent:.2f}%)'
            if key == 'voices_count' or key == 'video_notes_count':
                msg = '{msg} (длительностью {duration})'.format(
                    msg=msg,
                    duration=cls.__format_duration(
                        getattr(stat, key.replace('_count', '_duration'), 0)))
            counts.append(msg)
        counts_result = ''
        if len(counts) > 0:
            counts_sorted = sorted(counts,
                                   reverse=True,
                                   key=lambda s: int(s.split(' ')[0]))
            counts_result = '{}'.format(',\n'.join(counts_sorted)) + '.'

        # реплаи
        replies_keys_order = [
            'sent_replies_count', 'received_replies_count',
            'sent_mentions_count', 'received_mentions_count'
        ]
        replies_keys = {
            'sent_replies_count':
            'реплай отправлен, реплая отправлено, реплаев отправлено',
            'received_replies_count':
            'реплай получен, реплая получено, реплаев получено',
            'sent_mentions_count':
            ('раз тегала сама, раза тегала сама, раз тегала сама',
             'раз тегал сам, раза тегал сам, раз тегал сам'),
            'received_mentions_count':
            ('раз тегали ее, раза тегали ее, раз тегали ее',
             'раз тегали его, раза тегали его, раз тегали его'),
        }
        replies = []
        for key in replies_keys_order:
            plural_variants = replies_keys[key]
            if isinstance(plural_variants, tuple):
                plural_variants = plural_variants[
                    0] if user.female else plural_variants[1]
            count = getattr(stat, key, None)
            if count is None or count == 0 or count == '':
                continue
            msg = pytils.numeral.get_plural(count, plural_variants)
            replies.append(msg)
        replies_result = ''
        if len(replies) > 0:
            replies_result = ',\n'.join(replies) + '.'

        # домены
        top_domain = ''
        if stat.top_domain is not None and stat.top_domain != '':
            top_domain = '{count} упомянут домен {domain}'.format(
                count=pytils.numeral.get_plural(
                    UserDomains.get_user_domain_count(monday, uid, cid,
                                                      stat.top_domain),
                    'раз, раза, раз',
                    absence='Чаще всего'),
                domain=stat.top_domain)

        # результат
        results = [
            x for x in [counts_result, replies_result, top_domain] if x != ''
        ]
        return "\n\n".join(results)
Example #12
0
 def __get_cache_key(self, date: Optional[datetime] = None) -> str:
     date = get_current_monday() if date is None else get_date_monday(date)
     return f'i_stat:{date.strftime("%Y%m%d")}:{self.chat_id}'