diff --git a/src/data_types/frequency.py b/src/data_types/frequency.py index 695a6a9..4eb622d 100644 --- a/src/data_types/frequency.py +++ b/src/data_types/frequency.py @@ -2,7 +2,7 @@ from typing import List from datetime import timedelta import calendar -from utils import str_date, str_datetime, from_now, plural, percent +from utils import str_date, str_datetime, from_now, plural, percent, precise, top_key class Frequency: @@ -20,8 +20,8 @@ class Frequency: def to_string(self) -> List[str]: delta = self.dates[-1] - self.dates[0] total_msg = len(self.dates) - busiest_weekday = sorted(self.week)[-1] - busiest_hour = sorted(self.day)[-1] + busiest_weekday = top_key(self.week) + busiest_hour = top_key(self.day) n_weekdays = delta.days // 7 if ( self.dates[0].weekday() <= busiest_weekday @@ -34,11 +34,11 @@ class Frequency: return [ f"- **earliest message**: {str_datetime(self.dates[0])} ({from_now(self.dates[0])})", f"- **latest message**: {str_datetime(self.dates[-1])} ({from_now(self.dates[-1])})", - f"- **messages/day**: {total_msg/delta.days:,.2f}", - f"- **busiest day of week**: {calendar.day_name[busiest_weekday]} (~{self.week[busiest_weekday]/n_weekdays:,.2f} msg, {percent(self.week[busiest_weekday]/total_msg)})", + f"- **messages/day**: {precise(total_msg/delta.days, precision=3)}", + f"- **busiest day of week**: {calendar.day_name[busiest_weekday]} (~{precise(self.week[busiest_weekday]/n_weekdays, precision=3)} msg, {percent(self.week[busiest_weekday]/total_msg)})", f"- **busiest day ever**: {str_date(self.busiest_day)} ({from_now(self.busiest_day)}) ({self.busiest_day_count} msg)", - f"- **messages/hour**: {total_msg*3600/delta.total_seconds():,.2f}", - f"- **busiest hour of day**: {busiest_hour:0>2}:00 (~{self.day[busiest_hour]/n_hours:,.2f} msg, {percent(self.day[busiest_hour]/total_msg)})", + f"- **messages/hour**: {precise(total_msg*3600/delta.total_seconds(), precision=3)}", + f"- **busiest hour of day**: {busiest_hour:0>2}:00 (~{precise(self.day[busiest_hour]/n_hours, precision=3)} msg, {percent(self.day[busiest_hour]/total_msg)})", f"- **busiest hour ever**: {str_datetime(self.busiest_hour)} ({from_now(self.busiest_hour)}) ({self.busiest_hour_count} msg)", - f"- **longest break**: {plural(int(self.longest_break.total_seconds()/3600), 'hour')} ({plural(self.longest_break.days,'day')}) from {str_datetime(self.longest_break_start)} ({from_now(self.longest_break_start)})", + f"- **longest break**: {plural(round(self.longest_break.total_seconds()/3600), 'hour')} ({plural(self.longest_break.days,'day')}) from {str_datetime(self.longest_break_start)} ({from_now(self.longest_break_start)})", ] diff --git a/src/data_types/presence.py b/src/data_types/presence.py index 5c6661a..895a608 100644 --- a/src/data_types/presence.py +++ b/src/data_types/presence.py @@ -37,8 +37,11 @@ class Presence: )[-1] ret += [ f"- **most visited channel**: {channel_mention(top_channel)} ({self.channel_usage[top_channel]:,} msg, {percent(self.channel_usage[top_channel]/channel_sum)})", - f"- **mostly found in**: {channel_mention(found_in)} ({self.channel_usage[found_in]:,} msg, {percent(self.channel_usage[found_in]/self.channel_total[found_in])} of channel's)", ] + if member_specific: + ret += [ + f"- **mostly found in**: {channel_mention(found_in)} ({self.channel_usage[found_in]:,} msg, {percent(self.channel_usage[found_in]/self.channel_total[found_in])} of channel's)" + ] if member_specific: if len(self.mentions) > 0: top_mention = top_key(self.mentions) diff --git a/src/scanners/emotes_scanner.py b/src/scanners/emotes_scanner.py index 58e1f3d..7e53501 100644 --- a/src/scanners/emotes_scanner.py +++ b/src/scanners/emotes_scanner.py @@ -8,7 +8,7 @@ import discord from logs import ChannelLogs, MessageLog from data_types import Emote, get_emote_dict from .scanner import Scanner -from utils import emojis, COMMON_HELP_ARGS +from utils import emojis, COMMON_HELP_ARGS, plural, precise class EmotesScanner(Scanner): @@ -50,8 +50,7 @@ class EmotesScanner(Scanner): len(self.members) == 0 or len(self.members) > 1 ) # Create emotes dict from custom emojis of the guild - # Create emotes dict from custom emojis of the guild - self.emotes = get_emote_dict(message.channel.guild) + self.emotes = get_emote_dict(guild) return True def compute_message(self, channel: ChannelLogs, message: MessageLog): @@ -79,10 +78,10 @@ class EmotesScanner(Scanner): usage_count += self.emotes[name].usages reaction_count += self.emotes[name].reactions res += [ - f"Total: {usage_count:,} times ({usage_count / self.msg_count:.4f} / message)" + f"Total: {plural(usage_count,'time')} ({precise(usage_count/self.msg_count)}/msg)" ] if reaction_count > 0: - res[-1] += f" and {reaction_count:,} reactions" + res[-1] += f" and {plural(reaction_count, 'reaction')}" return res @staticmethod @@ -95,7 +94,7 @@ class EmotesScanner(Scanner): ) -> bool: impacted = False # If author is included in the selection (empty list is all) - if not message.bot and (len(raw_members) == 0 or message.author in raw_members): + if not message.bot and len(raw_members) == 0 or message.author in raw_members: impacted = True # Find all emotes un the current message in the form "<:emoji:123456789>" # Filter for known emotes diff --git a/src/scanners/full_scanner.py b/src/scanners/full_scanner.py index f0fd196..4721fd2 100644 --- a/src/scanners/full_scanner.py +++ b/src/scanners/full_scanner.py @@ -1,13 +1,12 @@ from typing import List -from collections import defaultdict import discord # Custom libs from .scanner import Scanner -from . import FrequencyScanner, CompositionScanner, PresenceScanner, EmotesScanner -from data_types import Frequency, Composition, Presence, get_emote_dict +from . import FrequencyScanner, CompositionScanner, PresenceScanner +from data_types import Frequency, Composition, Presence from logs import ChannelLogs, MessageLog from utils import COMMON_HELP_ARGS @@ -31,7 +30,6 @@ class FullScanner(Scanner): ) async def init(self, message: discord.Message, *args: str) -> bool: - guild = message.channel.guild self.freq = Frequency() self.compo = Composition() self.pres = Presence() @@ -42,8 +40,10 @@ class FullScanner(Scanner): FrequencyScanner.analyse_message(message, self.freq, self.raw_members) CompositionScanner.analyse_message(message, self.compo, self.raw_members) PresenceScanner.analyse_message(channel, message, self.pres, self.raw_members) - return not message.bot and ( - len(self.raw_members) == 0 or message.author in self.raw_members + return ( + not message.bot + and len(self.raw_members) == 0 + or message.author in self.raw_members ) def get_results(self, intro: str) -> List[str]: diff --git a/src/scanners/presence_scanner.py b/src/scanners/presence_scanner.py index 66e52a7..9d9dbcc 100644 --- a/src/scanners/presence_scanner.py +++ b/src/scanners/presence_scanner.py @@ -57,7 +57,7 @@ class PresenceScanner(Scanner): ) -> bool: impacted = False # If author is included in the selection (empty list is all) - if not message.bot and (len(raw_members) == 0 or message.author in raw_members): + if not message.bot and len(raw_members) == 0 or message.author in raw_members: impacted = True pres.channel_usage[channel.id] += 1 for mention in message.mentions: diff --git a/src/utils/utils.py b/src/utils/utils.py index b84d1b5..fa6d3a8 100644 --- a/src/utils/utils.py +++ b/src/utils/utils.py @@ -108,8 +108,10 @@ def percent(p: float) -> str: return f"{precise(100*p)}%" -def precise(p: float) -> str: - precision = abs(min(0, math.ceil(math.log10(p)) - 2)) +def precise(p: float, *, precision: int = 2) -> str: + if p == 0: + return "0" + precision = abs(min(0, math.ceil(math.log10(p)) - precision)) s = "{:." + str(precision) + "f}" return s.format(p)