def get_member_info(channel_model: ChannelModel) -> List[MemberInfoEntry]: ret = [] prof_conns = ProfileManager.get_channel_members(channel_model.id, available_only=True) user_oids = [mdl.user_oid for mdl in prof_conns] user_name_dict = IdentitySearcher.get_batch_user_name( user_oids, channel_model) last_message_oids = MessageRecordStatisticsManager.get_user_last_message_ts( channel_model.id, user_oids) for prof_conn in prof_conns: user_oid = prof_conn.user_oid user_name = user_name_dict.get(user_oid) or str(user_oid) first_joined = localtime(prof_conn.id.generation_time) last_message_at = last_message_oids.get(user_oid) if last_message_at: last_message_at = localtime(last_message_at) ret.append( MemberInfoEntry(user_oid=user_oid, user_name=user_name, first_joined=first_joined, last_message_at=last_message_at)) return ret
def get_per_user_bot_usage( channel_data: ChannelModel, *, hours_within: Optional[int] = None) \ -> PerMemberStats: data = [] features = [f for f in BotFeature] members = ProfileManager.get_channel_members(channel_data.id, available_only=True) usage_data = BotFeatureUsageDataManager.get_channel_per_user_usage( channel_data.id, hours_within=hours_within, member_oid_list=[d.user_oid for d in members]).data uid_handled = IdentitySearcher.get_batch_user_name( usage_data.keys(), channel_data) for uid, name in uid_handled.items(): usage_dict = usage_data[uid] data.append( PerMemberStatsEntry( user_name=name, data_points=[usage_dict.get(ft, 0) for ft in features], data_sum=sum(usage_dict.values()))) return PerMemberStats(data=data, features=features)
def get_user_daily_message( channel_data: ChannelModel, *, hours_within: Optional[int] = None, start: Optional[datetime] = None, end: Optional[datetime] = None, tz: Optional[tzinfo] = None, available_only: Optional[bool] = True) \ -> UserDailyMessageResult: available_dict = { d.user_oid: d.available for d in ProfileManager.get_channel_members( channel_data.id, available_only=available_only) } uname_dict = IdentitySearcher.get_batch_user_name(list( available_dict.keys()), channel_data, on_not_found="(N/A)") result = MessageRecordStatisticsManager.member_daily_message_count( channel_data.id, hours_within=hours_within, start=start, end=end, tzinfo_=tz) # Array for storing active member count actv_mbr = [] # Create empty arrays for the result # Each entry corresponds to daily message count in a specific date # Ordered by the date proc_count = {} proc_rank = {} for oid in uname_dict.keys(): proc_count[oid] = [] proc_rank[oid] = [] for date in result.dates: # Get the data of the corresponding date data_of_date = result.data_count[date] # Storing active member count actv_mbr.append(len(data_of_date)) # Get and sort the daily message count collated_count = { oid: data_of_date.get(oid, 0) for oid in proc_count.keys() } sorted_count = list( sorted(collated_count.items(), key=lambda x: x[1], reverse=True)) # Insert daily count and rank for rank, entry in enumerate_ranking( sorted_count, is_tie=lambda cur, prv: cur[1] == prv[1]): uid, count = entry proc_count[uid].append(count) proc_rank[uid].append(rank) entries = [ UserDailyMessageEntry(member_name=name, count_list=proc_count[oid], rank_list=proc_rank[oid], available=available_dict[oid]) for oid, name in uname_dict.items() ] return UserDailyMessageResult(label_dates=result.dates, entries=entries, active_members=actv_mbr)
def _get_user_msg_stats_(msg_result: MemberMessageByCategoryResult, ch_data: Union[ChannelModel, ChannelCollectionModel] = None, available_only: bool = True) -> UserMessageStats: entries: List[UserMessageStatsEntry] = [] if isinstance(ch_data, ChannelModel): ch_oids = [ch_data.id] elif isinstance(ch_data, ChannelCollectionModel): ch_oids = ch_data.child_channel_oids else: raise ValueError( f"The type of `ch_data` must either be `ChannelModel` or `ChannelCollectionModel`. " f"({type(ch_data)})") msg_rec_d = {uid: d for uid, d in msg_result.data.items()} msg_rec = {} available_dict = {} for member in ProfileManager.get_channel_members( ch_oids, available_only=available_only): msg_rec[member.user_oid] = msg_rec_d.get( member.user_oid, msg_result.get_default_data_entry()) available_dict[member.user_oid] = member.available if msg_rec: individual_msgs = [vals.total for vals in msg_rec.values()] max_individual_msg: int = max(individual_msgs) uid_handled = IdentitySearcher.get_batch_user_name( msg_rec.keys(), ch_data, on_not_found="(N/A)") for uid, name in uid_handled.items(): data_cat = msg_rec[uid] sum_ = data_cat.total cat_count = [] CategoryEntry = namedtuple("CategoryEntry", ["count", "percentage"]) for cat in msg_result.label_category: ct = data_cat.get_count(cat) cat_count.append( CategoryEntry(count=ct, percentage=ct / sum_ * 100 if sum_ > 0 else 0)) entries.append( UserMessageStatsEntry( user_oid=uid, user_name=name, category_count=cat_count, available=available_dict[uid], total_count=sum_, total_count_ratio=sum_ / max_individual_msg if max_individual_msg > 0 else 0)) return UserMessageStats(org_stats=entries, msg_count=sum(individual_msgs), label_category=msg_result.label_category) else: return UserMessageStats(org_stats=[], msg_count=0, label_category=msg_result.label_category)