mirror of
https://gitlab.com/chicken-riders/RcGcDw.git
synced 2025-02-22 00:14:10 +00:00
Added #24 however still not usable
This commit is contained in:
parent
468c381883
commit
fda8e6c25a
1
setup.py
1
setup.py
|
@ -12,5 +12,6 @@ setup(
|
|||
keywords=['MediaWiki', 'recent changes', 'Discord', 'webhook'],
|
||||
package_dir={"": "src"},
|
||||
install_requires=["beautifulsoup4 >= 4.6.0", "requests >= 2.18.4", "schedule >= 0.5.0", "lxml >= 4.2.1"],
|
||||
extras_require=["matplotlib => 3.4.3"],
|
||||
python_requires="3.7"
|
||||
)
|
||||
|
|
|
@ -17,6 +17,8 @@ import json
|
|||
import math
|
||||
import random
|
||||
from collections import defaultdict
|
||||
from typing import Tuple, Dict, Union
|
||||
from io import BytesIO
|
||||
|
||||
from src.configloader import settings
|
||||
|
||||
|
@ -36,6 +38,7 @@ class DiscordMessage:
|
|||
|
||||
self.message_type = message_type
|
||||
self.event_type = event_type
|
||||
self.files: Dict[str, Tuple[str, Union[BytesIO, str], str]] = {}
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
"""Set item is used only in embeds."""
|
||||
|
@ -63,6 +66,9 @@ class DiscordMessage:
|
|||
self.finish_embed()
|
||||
self.__setup_embed()
|
||||
|
||||
def add_file(self, filename: str, content: Union[str, BytesIO]):
|
||||
self.files[filename] = (None if isinstance(content, str) else filename, content, "application/json" if isinstance(content, str) else "image/" + filename.split(".")[1])
|
||||
|
||||
def finish_embed(self):
|
||||
if self.message_type != "embed":
|
||||
return
|
||||
|
|
|
@ -129,10 +129,18 @@ def update_ratelimit(request):
|
|||
def send_to_discord_webhook(data: Optional[DiscordMessage], metadata: DiscordMessageMetadata):
|
||||
global rate_limit
|
||||
header = settings["header"]
|
||||
header['Content-Type'] = 'application/json'
|
||||
if data.files:
|
||||
header['Content-Type'] = 'multipart/form-data'
|
||||
else:
|
||||
header['Content-Type'] = 'application/json'
|
||||
standard_args = dict(headers=header)
|
||||
if metadata.method == "POST":
|
||||
req = requests.Request("POST", data.webhook_url+"?wait=" + ("true" if AUTO_SUPPRESSION_ENABLED else "false"), data=repr(data), **standard_args)
|
||||
if data.files:
|
||||
data.add_file("payload_json", repr(data))
|
||||
logger.debug(data.files)
|
||||
req = requests.Request("POST", data.webhook_url+"?wait=" + ("true" if AUTO_SUPPRESSION_ENABLED else "false"), files=data.files, **standard_args)
|
||||
else:
|
||||
req = requests.Request("POST", data.webhook_url+"?wait=" + ("true" if AUTO_SUPPRESSION_ENABLED else "false"), data=repr(data), **standard_args)
|
||||
elif metadata.method == "DELETE":
|
||||
req = requests.Request("DELETE", metadata.webhook_url, **standard_args)
|
||||
elif metadata.method == "PATCH":
|
||||
|
|
|
@ -18,13 +18,13 @@
|
|||
|
||||
# WARNING! SHITTY CODE AHEAD. ENTER ONLY IF YOU ARE SURE YOU CAN TAKE IT
|
||||
# You have been warned
|
||||
|
||||
import time, logging.config, requests, datetime, math, os.path, schedule, sys, re, importlib
|
||||
import io
|
||||
import time, logging.config, requests, datetime, math, os.path, schedule, sys, importlib
|
||||
|
||||
import src.misc
|
||||
from collections import defaultdict, Counter, OrderedDict
|
||||
|
||||
from typing import Optional
|
||||
from typing import Optional, List
|
||||
import src.api.client
|
||||
from src.api.context import Context
|
||||
from src.api.hooks import formatter_hooks, pre_hooks, post_hooks
|
||||
|
@ -42,15 +42,23 @@ ngettext = rcgcdw.ngettext
|
|||
|
||||
TESTING = True if "--test" in sys.argv else False # debug mode, pipeline testing
|
||||
AUTO_SUPPRESSION_ENABLED = settings.get("auto_suppression", {"enabled": False}).get("enabled")
|
||||
PLOTTING_ENABLED = settings.get("event_appearance", {}).get("daily_overview", {}).get("plot", False)
|
||||
|
||||
if AUTO_SUPPRESSION_ENABLED:
|
||||
from src.discord.redaction import delete_messages, redact_messages
|
||||
|
||||
# Prepare logging
|
||||
|
||||
logging.config.dictConfig(settings["logging"])
|
||||
logger = logging.getLogger("rcgcdw")
|
||||
logger.debug("Current settings: {settings}".format(settings=settings))
|
||||
|
||||
if PLOTTING_ENABLED:
|
||||
try:
|
||||
import matplotlib.pyplot as plt
|
||||
from matplotlib.ticker import MultipleLocator
|
||||
except ImportError:
|
||||
logger.error("matplotlib is not installed. Install matplotlib with pip install matplotlib if you want to use plots in daily overview.")
|
||||
|
||||
def load_extensions():
|
||||
"""Loads all of the extensions, can be a local import because all we need is them to register"""
|
||||
|
@ -121,6 +129,27 @@ def daily_overview_sync(data: dict) -> dict:
|
|||
return data_output
|
||||
|
||||
|
||||
def overview_plot_generation(hours: defaultdict[int, int]) -> io.BytesIO:
|
||||
"""Generates plot image using matplotlib"""
|
||||
output = io.BytesIO()
|
||||
current_hour, axes_data = datetime.datetime.utcnow().hour, [[], []]
|
||||
for __ in range(24):
|
||||
axes_data[0].append(current_hour)
|
||||
axes_data[1].append(hours.get(current_hour, 0))
|
||||
current_hour += 1
|
||||
if current_hour > 23:
|
||||
current_hour = 0
|
||||
fig, ax = plt.subplots()
|
||||
plt.bar(axes_data[0], axes_data[1])
|
||||
plt.xlabel(_('Hour (UTC)'))
|
||||
plt.ylabel(_('Actions'))
|
||||
ax.set_xlim(-0.5, 23.5)
|
||||
ax.set_xticklabels([str(axes_data[0][0])] + [str(x) for x in axes_data[0]])
|
||||
ax.xaxis.set_major_locator(MultipleLocator(1))
|
||||
plt.savefig(output, format="png")
|
||||
return output
|
||||
|
||||
|
||||
def day_overview():
|
||||
try:
|
||||
result = day_overview_request()
|
||||
|
@ -146,7 +175,7 @@ def day_overview():
|
|||
if "actionhidden" in item or "suppressed" in item or "userhidden" in item:
|
||||
continue # while such actions have type value (edit/new/log) many other values are hidden and therefore can crash with key error, let's not process such events
|
||||
activity = add_to_dict(activity, item["user"])
|
||||
hours = add_to_dict(hours, datetime.datetime.strptime(item["timestamp"], "%Y-%m-%dT%H:%M:%SZ").hour)
|
||||
hours = add_to_dict(hours, datetime.datetime.strptime(item["timestamp"], "%Y-%m-%dT%H:%M:%SZ").hour) # Edits can overlap between days at same hour if overview executes in non full hour, but let's ignore that
|
||||
if item["type"] == "edit":
|
||||
edits += 1
|
||||
changed_bytes += item["newlen"] - item["oldlen"]
|
||||
|
@ -190,6 +219,11 @@ def day_overview():
|
|||
)
|
||||
for name, value in fields:
|
||||
embed.add_field(name, value, inline=True)
|
||||
if PLOTTING_ENABLED:
|
||||
file = overview_plot_generation(hours)
|
||||
file_name = "_" + datetime.datetime.now().strftime("%Y-%m-%d_%H:%M") + "_wiki_overview.png"
|
||||
embed.add_file(file_name, file)
|
||||
embed["image"]["url"] = "attachment://" + file_name
|
||||
embed.finish_embed()
|
||||
send_to_discord(embed, meta=DiscordMessageMetadata("POST"))
|
||||
|
||||
|
|
Loading…
Reference in a new issue