start en stop dates
This commit is contained in:
+73
-25
@@ -1,15 +1,21 @@
|
||||
from calendar import month
|
||||
from typing import List, Dict, Union, Optional, Any
|
||||
import os
|
||||
import logging
|
||||
import discord
|
||||
import math
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timedelta
|
||||
import re
|
||||
import dateutil.parser
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
# OTHER
|
||||
|
||||
COMMON_HELP_ARGS = [
|
||||
"@member/me - filter for one or more member",
|
||||
"#channel/here - filter for one or more channel",
|
||||
"<date1> - filter after <date1>",
|
||||
"<date2> - filter before <date2>",
|
||||
"fast - only read cache",
|
||||
"fresh - does not read cache (long)",
|
||||
]
|
||||
@@ -30,6 +36,7 @@ def generate_help(
|
||||
%{cmd}: {info}
|
||||
arguments:
|
||||
{arg_list}
|
||||
(Dates are formated 'yyyy-mm-dd' or 'yyyy-mm-ddThh:mm' (ISO 8601) or 'week/month/year')
|
||||
Example: %{cmd} {example}
|
||||
```"""
|
||||
|
||||
@@ -153,6 +160,37 @@ def precise(p: float, *, precision: int = 2) -> str:
|
||||
|
||||
# DATE FORMATTING
|
||||
|
||||
ISO8601_REGEX = r"^([\+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?|W([0-4]\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-3])((:?)[0-5]\d)?|24\:?00)([\.,]\d+(?!:))?)?(\17[0-5]\d([\.,]\d+)?)?([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$"
|
||||
ISO8601_FULL = "0000-01-01T00:00:00"
|
||||
|
||||
|
||||
def parse_iso_datetime(str_date: str) -> datetime:
|
||||
if re.match(
|
||||
"^\d{4}(-\d{2}(-\d{2}(T\d{2}(:\d{2}(:\d{2}(:\d{2})?)?)?)?)?)?$", str_date
|
||||
):
|
||||
str_date = str_date + "0000-01-01T00:00:00"[len(str_date) :]
|
||||
return dateutil.parser.parse(str_date)
|
||||
|
||||
|
||||
RELATIVE_TIME = {
|
||||
"today": relativedelta(days=1),
|
||||
"yesterday": relativedelta(days=2),
|
||||
"week": relativedelta(weeks=1),
|
||||
"month": relativedelta(months=1),
|
||||
"year": relativedelta(years=1),
|
||||
}
|
||||
|
||||
|
||||
def parse_relative_time(src: str) -> datetime:
|
||||
return datetime.utcnow() - RELATIVE_TIME[src]
|
||||
|
||||
|
||||
def parse_time(src: str) -> datetime:
|
||||
if src in RELATIVE_TIME:
|
||||
return parse_relative_time(src)
|
||||
else:
|
||||
return parse_iso_datetime(src)
|
||||
|
||||
|
||||
def str_date(date: datetime) -> str:
|
||||
return date.strftime("%d %b. %Y") # 12 Jun. 2018
|
||||
@@ -162,29 +200,37 @@ def str_datetime(date: datetime) -> str:
|
||||
return date.strftime("%H:%M, %d %b. %Y") # 12:05, 12 Jun. 2018
|
||||
|
||||
|
||||
def from_now(src: Optional[datetime]) -> str:
|
||||
if src is None:
|
||||
return "never"
|
||||
delay = datetime.utcnow() - src
|
||||
def str_delta(delay: timedelta) -> str:
|
||||
seconds = delay.seconds
|
||||
minutes = seconds // 60
|
||||
hours = minutes // 60
|
||||
if delay.days < 1:
|
||||
if hours < 1:
|
||||
if minutes == 0:
|
||||
return "now"
|
||||
return "no time"
|
||||
elif minutes == 1:
|
||||
return "a minute ago"
|
||||
return "a minute"
|
||||
else:
|
||||
return f"{minutes} minutes ago"
|
||||
return f"{minutes} minutes"
|
||||
elif hours == 1:
|
||||
return "an hour ago"
|
||||
return "an hour"
|
||||
else:
|
||||
return f"{hours} hours ago"
|
||||
return f"{hours} hours"
|
||||
elif delay.days == 1:
|
||||
return "yesterday"
|
||||
return "one day"
|
||||
else:
|
||||
return f"{delay.days:,} days ago"
|
||||
return f"{delay.days:,} days"
|
||||
|
||||
|
||||
def from_now(src: Optional[datetime]) -> str:
|
||||
if src is None:
|
||||
return "never"
|
||||
output = str_delta(datetime.utcnow() - src)
|
||||
if output == "no time":
|
||||
return "now"
|
||||
elif output == "one day":
|
||||
return "yesterday"
|
||||
return output + " ago"
|
||||
|
||||
|
||||
# APP SPECIFIC
|
||||
@@ -197,46 +243,48 @@ def get_intro(
|
||||
members: List[discord.Member],
|
||||
nmm: int, # number of messages impacted
|
||||
nc: int, # number of impacted channels
|
||||
start_datetime: datetime,
|
||||
stop_datetime: datetime,
|
||||
) -> str:
|
||||
"""
|
||||
Get the introduction sentence of the response
|
||||
"""
|
||||
time_text = ""
|
||||
if start_datetime is not None:
|
||||
stop_datetime = datetime.now() if stop_datetime is None else stop_datetime
|
||||
time_text = f" (in {str_delta(stop_datetime - start_datetime)})"
|
||||
# Show all data (members, channels) when it's less than 5 units
|
||||
if len(members) == 0:
|
||||
# Full scan of the server
|
||||
if full:
|
||||
return f"{subject} in this server ({nc} channels, {nmm:,} messages):"
|
||||
return f"{subject} in this server ({nc} channels, {nmm:,} messages){time_text}:"
|
||||
elif len(channels) < 5:
|
||||
return f"{aggregate([c.mention for c in channels])} {subject.lower()} in {nmm:,} messages:"
|
||||
return f"{aggregate([c.mention for c in channels])} {subject.lower()} in {nmm:,} messages{time_text}:"
|
||||
else:
|
||||
return (
|
||||
f"These {len(channels)} channels {subject.lower()} in {nmm:,} messages:"
|
||||
)
|
||||
return f"These {len(channels)} channels {subject.lower()} in {nmm:,} messages{time_text}:"
|
||||
elif len(members) < 5:
|
||||
if full:
|
||||
return f"{aggregate([m.mention for m in members])} {subject.lower()} in {nmm:,} messages:"
|
||||
return f"{aggregate([m.mention for m in members])} {subject.lower()} in {nmm:,} messages{time_text}:"
|
||||
elif len(channels) < 5:
|
||||
return (
|
||||
f"{aggregate([m.mention for m in members])} on {aggregate([c.mention for c in channels])} "
|
||||
f"{subject.lower()} in {nmm:,} messages:"
|
||||
f"{subject.lower()} in {nmm:,} messages{time_text}:"
|
||||
)
|
||||
else:
|
||||
return (
|
||||
f"{aggregate([m.mention for m in members])} on these {len(channels)} channels "
|
||||
f"{subject.lower()} in {nmm:,} messages:"
|
||||
f"{subject.lower()} in {nmm:,} messages{time_text}:"
|
||||
)
|
||||
else:
|
||||
if full:
|
||||
return (
|
||||
f"These {len(members)} members {subject.lower()} in {nmm:,} messages:"
|
||||
)
|
||||
return f"These {len(members)} members {subject.lower()} in {nmm:,} messages{time_text}:"
|
||||
elif len(channels) < 5:
|
||||
return (
|
||||
f"These {len(members)} members on {aggregate([c.mention for c in channels])} "
|
||||
f"{subject.lower()} in {nmm:,} messages:"
|
||||
f"{subject.lower()} in {nmm:,} messages{time_text}:"
|
||||
)
|
||||
else:
|
||||
return (
|
||||
f"These {len(members)} members on these {len(channels)} channels "
|
||||
f"{subject.lower()} in {nmm:,} messages:"
|
||||
f"{subject.lower()} in {nmm:,} messages{time_text}:"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user