Exemplo n.º 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}
Exemplo n.º 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'])
     }
Exemplo n.º 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]
     }
Exemplo n.º 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)
Exemplo n.º 5
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 []
Exemplo n.º 6
0
    def update_user_top_domain(cls, uid, cid, url):
        domain = cls.__parse_domain(url)

        # в мемкеше хранятся все домены пользователя за текущую неделю с количеством использований
        monday = get_current_monday()
        logger.debug(f'update_user_top_domain_lock {cid}:{uid}')
        with cls.lock:
            cache_key = cls.__get_user_domain_cache_key(monday, uid, cid)
            user_domains = cache.get(cache_key)
            if user_domains is None:
                user_domains = {}
            user_domains.setdefault(domain, 0)
            user_domains[domain] = user_domains[domain] + 1
            cache.set(cache_key, user_domains, time=USER_CACHE_EXPIRE)

        # самый часто используемый домен
        top_domain = max(user_domains, key=user_domains.get)
        return top_domain
Exemplo n.º 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
Exemplo n.º 8
0
 def add(cls, added_stat: 'UserStat') -> None:
     if added_stat.uid == bot_id():
         return
     monday = get_current_monday()
     added_stat.stats_monday = monday
     uid = added_stat.uid
     cid = added_stat.cid
     key = cls.__get_cache_key(monday, uid, cid)
     logger.debug(f'add_lock {cid}:{uid}')
     # стата обновляется постоянно, поэтому лок сразу
     with cls.add_lock:
         old_stat = cls.get(monday, uid, cid)
         try:
             if old_stat is not None:
                 updated_stat = cls.__update(old_stat, added_stat)
                 cache.set(key, updated_stat, time=USER_CACHE_EXPIRE)
                 return
             UserStatDB.add(added_stat)
             cache.set(key, added_stat, time=USER_CACHE_EXPIRE)
         except Exception as e:
             logger.error(e)
Exemplo n.º 9
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
Exemplo n.º 10
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)
Exemplo n.º 11
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
        }
Exemplo n.º 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}'