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}
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']) }
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] }
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)
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 []
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
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
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)
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
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)
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 }
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}'