feat: (BETA) %freq graph

This commit is contained in:
Klemek
2021-07-13 18:04:46 +02:00
parent 07aed12463
commit 8b0fe859a7
4 changed files with 68 additions and 8 deletions
+2
View File
@@ -2,3 +2,5 @@ discord.py==1.7.0
python-dotenv==0.15.0 python-dotenv==0.15.0
python-dateutil==2.8.1 python-dateutil==2.8.1
git+git://github.com/Klemek/miniscord.git git+git://github.com/Klemek/miniscord.git
numpy
matplotlib
+44
View File
@@ -1,6 +1,11 @@
from typing import List from typing import List
from datetime import timedelta from datetime import timedelta
import calendar import calendar
import matplotlib.pyplot as plt
import numpy as np
from io import BytesIO
import discord
import time
from utils import ( from utils import (
from_now, from_now,
@@ -30,6 +35,45 @@ class Frequency:
self.longest_streak_start = None self.longest_streak_start = None
self.longest_streak_author = None self.longest_streak_author = None
def to_graph(self) -> List[str]:
self.dates.sort()
delta = self.dates[-1] - self.dates[0]
if delta.days == 0:
delta = timedelta(days=1)
day = {j: sum(self.hours[i][j] for i in range(7)) for j in range(24)}
busiest_hour = top_key(day)
n_hours = delta.days
if self.dates[0].hour <= busiest_hour and self.dates[-1].hour >= busiest_hour:
n_hours += 1
plt.style.use('dark_background')
fig, ax = plt.subplots()
fig.patch.set_facecolor('#36393F')
ax.patch.set_alpha(0)
times = range(25)
for i in range(7):
hours = [self.hours[i][hour]*7/n_hours for hour in range(24)] + [self.hours[i][0]*7/n_hours]
ax.plot(times, hours, label=calendar.day_name[i], linestyle='--', linewidth=0.8)
hours = [day[hour]/n_hours for hour in range(24)] + [day[0]/n_hours]
ax.plot(times, hours, c='r', label='average', linewidth=1.5)
ax.set_xlabel('hour of day')
ax.set_xlim([0, 24])
ax.set_ylabel('average messages')
ax.legend(framealpha=0)
with BytesIO() as f:
plt.savefig(f, format='png', facecolor=fig.get_facecolor(), edgecolor='none')
f.seek(0)
return [
discord.File(f, f"{time.time()}-plot.png")
]
def to_string( def to_string(
self, self,
*, *,
+12 -6
View File
@@ -14,11 +14,13 @@ from utils import generate_help
class FrequencyScanner(Scanner): class FrequencyScanner(Scanner):
@staticmethod @staticmethod
def help() -> str: def help() -> str:
return generate_help("freq", "Show frequency-related statistics") return generate_help("freq", "(BETA) Show frequency-related statistics", args=[
"graph - plot hours of week",
],)
def __init__(self): def __init__(self):
super().__init__( super().__init__(
valid_args=["all", "everyone"], valid_args=["all", "everyone", "graph"],
help=FrequencyScanner.help(), help=FrequencyScanner.help(),
intro_context="Frequency", intro_context="Frequency",
) )
@@ -27,6 +29,7 @@ class FrequencyScanner(Scanner):
self.freq = Frequency() self.freq = Frequency()
self.all_messages = "all" in args or "everyone" in args self.all_messages = "all" in args or "everyone" in args
self.member_specific = len(self.members) > 0 self.member_specific = len(self.members) > 0
self.to_graph = "graph" in args
return True return True
def compute_message(self, channel: ChannelLogs, message: MessageLog): def compute_message(self, channel: ChannelLogs, message: MessageLog):
@@ -36,10 +39,13 @@ class FrequencyScanner(Scanner):
def get_results(self, intro: str) -> List[str]: def get_results(self, intro: str) -> List[str]:
FrequencyScanner.compute_results(self.freq) FrequencyScanner.compute_results(self.freq)
res = [intro] if self.to_graph:
res += self.freq.to_string( res = self.freq.to_graph()
member_specific=self.member_specific, else:
) res = [intro]
res += self.freq.to_string(
member_specific=self.member_specific,
)
return res return res
@staticmethod @staticmethod
+10 -2
View File
@@ -288,15 +288,20 @@ class Scanner(ABC):
if self.mention_users if self.mention_users
else discord.AllowedMentions.none() else discord.AllowedMentions.none()
) )
file = None
for r in results: for r in results:
if r: if r:
if isinstance(r, int) and r == SPLIT_TOKEN: if isinstance(r, discord.File):
file = r
elif isinstance(r, int) and r == SPLIT_TOKEN:
await message.channel.send( await message.channel.send(
response, response,
reference=message if first else None, reference=message if first else None,
allowed_mentions=allowed_mentions, allowed_mentions=allowed_mentions,
file=file,
) )
first = False first = False
file = None
response = "" response = ""
elif isinstance(r, str): elif isinstance(r, str):
if len(response + "\n" + r) > 2000: if len(response + "\n" + r) > 2000:
@@ -304,15 +309,18 @@ class Scanner(ABC):
response, response,
reference=message if first else None, reference=message if first else None,
allowed_mentions=allowed_mentions, allowed_mentions=allowed_mentions,
file=file,
) )
first = False first = False
file = None
response = "" response = ""
response += "\n" + r response += "\n" + r
if len(response) > 0: if len(response) > 0 or file is not None:
await message.channel.send( await message.channel.send(
response, response,
reference=message if first else None, reference=message if first else None,
allowed_mentions=allowed_mentions, allowed_mentions=allowed_mentions,
file=file,
) )
command_cache.cache(self, message, args) command_cache.cache(self, message, args)
# Delete custom progress message # Delete custom progress message