feat: (BETA) %freq graph
This commit is contained in:
@@ -2,3 +2,5 @@ discord.py==1.7.0
|
||||
python-dotenv==0.15.0
|
||||
python-dateutil==2.8.1
|
||||
git+git://github.com/Klemek/miniscord.git
|
||||
numpy
|
||||
matplotlib
|
||||
@@ -1,6 +1,11 @@
|
||||
from typing import List
|
||||
from datetime import timedelta
|
||||
import calendar
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
from io import BytesIO
|
||||
import discord
|
||||
import time
|
||||
|
||||
from utils import (
|
||||
from_now,
|
||||
@@ -30,6 +35,45 @@ class Frequency:
|
||||
self.longest_streak_start = 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(
|
||||
self,
|
||||
*,
|
||||
|
||||
@@ -14,11 +14,13 @@ from utils import generate_help
|
||||
class FrequencyScanner(Scanner):
|
||||
@staticmethod
|
||||
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):
|
||||
super().__init__(
|
||||
valid_args=["all", "everyone"],
|
||||
valid_args=["all", "everyone", "graph"],
|
||||
help=FrequencyScanner.help(),
|
||||
intro_context="Frequency",
|
||||
)
|
||||
@@ -27,6 +29,7 @@ class FrequencyScanner(Scanner):
|
||||
self.freq = Frequency()
|
||||
self.all_messages = "all" in args or "everyone" in args
|
||||
self.member_specific = len(self.members) > 0
|
||||
self.to_graph = "graph" in args
|
||||
return True
|
||||
|
||||
def compute_message(self, channel: ChannelLogs, message: MessageLog):
|
||||
@@ -36,10 +39,13 @@ class FrequencyScanner(Scanner):
|
||||
|
||||
def get_results(self, intro: str) -> List[str]:
|
||||
FrequencyScanner.compute_results(self.freq)
|
||||
res = [intro]
|
||||
res += self.freq.to_string(
|
||||
member_specific=self.member_specific,
|
||||
)
|
||||
if self.to_graph:
|
||||
res = self.freq.to_graph()
|
||||
else:
|
||||
res = [intro]
|
||||
res += self.freq.to_string(
|
||||
member_specific=self.member_specific,
|
||||
)
|
||||
return res
|
||||
|
||||
@staticmethod
|
||||
|
||||
+10
-2
@@ -288,15 +288,20 @@ class Scanner(ABC):
|
||||
if self.mention_users
|
||||
else discord.AllowedMentions.none()
|
||||
)
|
||||
file = None
|
||||
for r in results:
|
||||
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(
|
||||
response,
|
||||
reference=message if first else None,
|
||||
allowed_mentions=allowed_mentions,
|
||||
file=file,
|
||||
)
|
||||
first = False
|
||||
file = None
|
||||
response = ""
|
||||
elif isinstance(r, str):
|
||||
if len(response + "\n" + r) > 2000:
|
||||
@@ -304,15 +309,18 @@ class Scanner(ABC):
|
||||
response,
|
||||
reference=message if first else None,
|
||||
allowed_mentions=allowed_mentions,
|
||||
file=file,
|
||||
)
|
||||
first = False
|
||||
file = None
|
||||
response = ""
|
||||
response += "\n" + r
|
||||
if len(response) > 0:
|
||||
if len(response) > 0 or file is not None:
|
||||
await message.channel.send(
|
||||
response,
|
||||
reference=message if first else None,
|
||||
allowed_mentions=allowed_mentions,
|
||||
file=file,
|
||||
)
|
||||
command_cache.cache(self, message, args)
|
||||
# Delete custom progress message
|
||||
|
||||
Reference in New Issue
Block a user