예제 #1
0
    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
예제 #2
0
    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)
예제 #3
0
    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)
예제 #4
0
    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)