-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathconverters.py
156 lines (127 loc) · 4.33 KB
/
converters.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
import discord, warnings, csv, re, sys
from discord import app_commands
from discord.ext import commands
from datetime import timezone
from dateutil import parser as duparser
from . import utils
class Armiger(app_commands.Transformer, commands.Converter):
@property
def type(self):
return discord.AppCommandOptionType.user
async def transform(self, interaction, value: discord.Member):
result = await interaction.client.dbc.execute_fetchone(
"SELECT * FROM armigers_e WHERE discord_id == ?;",
(value.id,)
)
if result: return result
raise utils.CustomCommandError(
"Invalid armiger",
"The armiger you entered does not have arms recorded. Check that you spelled their name correctly."
)
async def convert(self, ctx, argument):
result = None
if argument.isdecimal():
result = await ctx.bot.dbc.execute_fetchone(
"SELECT * FROM armigers_e WHERE greii_n == ?;",
(int(argument),)
)
elif argument.startswith("<"):
try:
member = await commands.MemberConverter().convert(ctx, argument)
result = await ctx.bot.dbc.execute_fetchone(
"SELECT * FROM armigers_e WHERE discord_id == ?;",
(member.id,)
)
except commands.MemberNotFound: pass
else:
result = await ctx.bot.dbc.execute_fetchone(
"SELECT * FROM armigers_e WHERE qualified_name LIKE ?;",
(f"%{argument}%",)
)
if result: return result
raise utils.CustomCommandError(
"Invalid armiger",
"The armiger you entered does not have arms recorded. Check that you spelled their name correctly."
)
class Url(commands.Converter):
VALID = re.compile(r"\S+\.\S{1,4}\S*")
async def convert(self, ctx, argument):
if re.match(Url.VALID, argument):
return argument
else:
raise utils.CustomCommandError(
"Invalid URL",
f"The URL entered is not in the correct format."
)
class MemberOrUser(app_commands.Transformer, commands.Converter):
@property
def type(self):
return discord.AppCommandOptionType.user
async def transform(self, ctx, argument):
return argument
async def convert(self, ctx, argument):
try:
return await commands.MemberConverter().convert(ctx, argument)
except commands.MemberNotFound: pass
try:
return await commands.UserConverter().convert(ctx, argument)
except commands.UserNotFound: pass
#use the armigers db as a basis for partial matching,
#since discord.py only does whole matches (and it would be too
#inefficient to redo its behaviour with that)
query = await ctx.bot.dbc.execute_fetchone(
"SELECT * FROM armigers_e WHERE qualified_name LIKE ? AND discord_id IS NOT NULL",
(f"%{argument}%",)
)
if query:
user = await utils.get_user(ctx.bot, query["discord_id"])
if user: return user
raise commands.UserNotFound(argument)
class RollVariant(commands.Converter):
async def convert(self, ctx, argument):
variants = ctx.bot.get_cog("Roll Sorting").VARIANTS
try:
argument = int(argument)
return (*variants[argument], False)
except ValueError: pass
kw = tuple(v[1] for v in variants)
if argument in kw:
return (*variants[kw.index(argument)], False)
raise utils.CustomCommandError(
"Invalid roll variant",
"The item you entered is not a valid roll channel type."
)
class Date(commands.Converter):
def __init__(self):
warnings.simplefilter("error", duparser.UnknownTimezoneWarning)
if not getattr(Date, "timezones", 0):
#only do this once, and save it for all class members
with open("data/tz.csv") as file:
csvdata = {a: int(b) for (a, b) in csv.reader(file, delimiter = ";")}
setattr(Date, "timezones", csvdata)
async def convert(self, ctx, argument):
try:
date = duparser.parse(argument, fuzzy = True, tzinfos = self.timezones)
except ValueError:
raise utils.CustomCommandError(
"Invalid date",
"The date you entered is in an unrecognisable format."
)
except duparser.UnknownTimezoneWarning:
raise utils.CustomCommandError(
"Invalid timezone",
"The timezone you entered is invalid."
)
return date.astimezone(timezone.utc)
class ArchivedThread(app_commands.Transformer):
@property
def type(self):
return discord.AppCommandOptionType.channel
async def transform(self, interaction, value: int):
thread = await interaction.client.fetch_channel(value.id)
if not thread:
raise utils.CustomCommandError(
"Invalid thread",
"The thread is invalid."
)
return thread