autobotrobot/src/util.py

73 lines
2.6 KiB
Python
Raw Normal View History

2020-05-12 16:08:03 +00:00
import re
import datetime
import parsedatetime
2020-06-18 18:43:20 +00:00
import ast
import copy
2020-05-12 16:08:03 +00:00
from dateutil.relativedelta import relativedelta
# from here: https://github.com/Rapptz/RoboDanny/blob/18b92ae2f53927aedebc25fb5eca02c8f6d7a874/cogs/utils/time.py
short_timedelta_regex = re.compile("""
2020-06-18 18:43:20 +00:00
(?:(?P<years>[0-9]{1,8})(?:years?|y))? # e.g. 2y
(?:(?P<months>[0-9]{1,8})(?:months?|mo))? # e.g. 2months
(?:(?P<weeks>[0-9]{1,8})(?:weeks?|w))? # e.g. 10w
(?:(?P<days>[0-9]{1,8})(?:days?|d))? # e.g. 14d
(?:(?P<hours>[0-9]{1,8})(?:hours?|h))? # e.g. 12h
(?:(?P<minutes>[0-9]{1,8})(?:minutes?|m))? # e.g. 10m
(?:(?P<seconds>[0-9]{1,8})(?:seconds?|s))? # e.g. 15s """, re.VERBOSE)
2020-05-12 16:08:03 +00:00
def parse_short_timedelta(text):
match = short_timedelta_regex.fullmatch(text)
if match is None or not match.group(0): raise ValueError("parse failed")
data = { k: int(v) for k, v in match.groupdict(default=0).items() }
return datetime.datetime.utcnow() + relativedelta(**data)
cal = parsedatetime.Calendar()
def parse_humantime(text):
time_struct, parse_status = cal.parse(text)
if parse_status == 1: return datetime.datetime(*time_struct[:6])
else: raise ValueError("parse failed")
def parse_time(text):
try: return datetime.datetime.strptime(text, "%d/%m/%Y")
except: pass
try: return parse_short_timedelta(text)
except: pass
try: return parse_humantime(text)
except: pass
raise ValueError("could not parse time")
def format_time(dt):
2020-06-18 18:43:20 +00:00
return dt.strftime("%H:%M:%S %d/%m/%Y")
CODEBLOCK_REGEX = "^[^`]*```[a-zA-Z0-9_\-+]*\n(.+)```$"
CODELINE_REGEX = "^[^`]*`(.*)`$"
def extract_codeblock(s):
match1 = re.match(CODEBLOCK_REGEX, s, flags=re.DOTALL)
match2 = re.match(CODELINE_REGEX, s, flags=re.DOTALL)
if match1: return match1.group(1)
elif match2: return match2.group(1)
else:
return s.strip()
# from https://github.com/Gorialis/jishaku/blob/master/jishaku/repl/compilation.py
CORO_CODE = """
async def repl_coroutine():
import asyncio
import aiohttp
import discord
from discord.ext import commands
"""
async def async_exec(code, loc, glob):
user_code = ast.parse(code, mode='exec')
wrapper = ast.parse(CORO_CODE, mode='exec')
funcdef = wrapper.body[-1]
funcdef.body.extend(user_code.body)
last_expr = funcdef.body[-1]
if isinstance(last_expr, ast.Expr):
funcdef.body.pop()
funcdef.body.append(ast.Return(last_expr.value))
ast.fix_missing_locations(wrapper)
exec(compile(wrapper, "<repl>", "exec"), loc, glob)
return await (loc.get("repl_coroutine") or glob.get("repl_coroutine"))()