Newer
Older
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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
import utils
from cogs.help import text_command_help, help, handle_error, remove_help_for, help_category
@help_category("textcommands", "Text-Kommandos", "", "Alle Werkzeuge zum Anlegen und Verwalten von Textkommandos.")
class TextCommands(commands.Cog):
def __init__(self, bot):
self.bot = bot
self.text_commands = {}
self.cmd_file = os.getenv("DISCORD_TEXT_COMMANDS_FILE")
self.mod_channel_id = int(os.getenv("DISCORD_SUPPORT_CHANNEL"))
self.load_text_commands()
def load_text_commands(self):
""" Loads all appointments from APPOINTMENTS_FILE """
text_commands_file = open(self.cmd_file, mode='r')
self.text_commands = json.load(text_commands_file)
for cmd in self.text_commands:
help_for_cmd = self.text_commands[cmd].get('help')
if not help_for_cmd:
continue
brief = help_for_cmd.get('brief')
category = help_for_cmd.get('category')
if not brief:
text_command_help(cmd)
continue
text_command_help(cmd, brief=brief, category=category)
def save_text_commands(self):
text_commands_file = open(self.cmd_file, mode='w')
json.dump(self.text_commands, text_commands_file)
@commands.group(name="commands")
async def cmd_commands(self, ctx):
if not ctx.invoked_subcommand:
await ctx.send("Fehlerhafte Nutzung von `!commands`. "
"Bitte benutze `!help` um herauszufinden, wie dieses Kommando benutzt wird.")
@help(
category="textcommands",
brief="Listet alle verfügbaren Text-Commands auf oder die Texte, die zu einem Text-Command hinterlegt sind.",
syntax="!commands list <cmd?>",
example="!commands list !motivation",
description="Gibt bei Angabe eines Kommandos (optionaler Parameter cmd) die Texte, die für dieses Kommandu hinterlegt sind. ",
parameters={
"cmd": "*(optional)* Name des Kommandos, dessen Texte ausgegeben werden sollen."
}
)
@cmd_commands.command(name="list")
async def cmd_commands_list(self, ctx, cmd=None):
await self.list_commands(ctx, cmd)
@help(
category="textcommands",
brief="Schlägt ein Text-Kommando oder einen Text für ein bestehendes Text-Kommando vor.",
syntax="!commands add <cmd> <text> <help_message?> <category?>",
example="!command add !newcommand \"immer wenn newcommand aufgerufen wird wird das hier ausgegeben\" \"Hilfetext zu diesem Kommando\"",
description="Ein Text-Kommando ist ein Kommando welches über !<name des textkommandos> aufgerufen werden kann und dann zufällig einen der hinterlegten Texte ausgibt.",
parameters={
"cmd": "Name des anzulegenden Kommandos (z. B. !horoskop). ",
"text": "in Anführungszeichen eingeschlossene Textnachricht, die ausgegeben werden soll, wenn das Kommando aufgerufen wird (z. B. \"Wassermann: Findet diese Woche wahrscheinlich seinen Dreizack wieder.\").",
"help_message": "*(optional)* Die Hilfenachricht, die bei `!help` für dieses Kommando erscheinen soll (in Anführungszeichen). ",
"category": "*(optional)* gibt die Kategorie an in der das Kommando angezeigt werden soll. "
}
)
@cmd_commands.command(name="add")
async def cmd_commands_add(self, ctx, cmd, text, help_message=None, category=None):
if utils.is_mod(ctx):
await self.add_command(cmd, text, help_message=help_message, category=category)
else:
await self.suggest_command(ctx, cmd, text, help_message=help_message, category=category)
@help(
category="textcommands",
brief="Ändert den Text eines Text-Kommandos.",
syntax="!commands edit <cmd> <id> <text>",
example="!command edit !command 1 \"Neuer Text\"",
description="Ändert den Text eines Text-Kommandos an angegebenem Index.",
parameters={
"cmd": "Name des anzulegenden Kommandos (z. B. !horoskop). ",
"id": "Index des zu ändernden Texts.",
"text": "in Anführungszeichen eingeschlossene Textnachricht, die ausgegeben werden soll, wenn das Kommando aufgerufen wird (z. B. \"Wassermann: Findet diese Woche wahrscheinlich seinen Dreizack wieder.\").",
},
mod=True
)
@cmd_commands.command(name="edit")
@commands.check(utils.is_mod)
async def cmd_command_edit(self, ctx, cmd, id, text):
texts = self.text_commands.get(cmd).get('data')
if texts:
i = int(id)
if 0 <= i < len(texts):
texts[i] = text
await ctx.send(f"Text {i} für Command {cmd} wurde erfolgreich geändert")
self.save_text_commands()
else:
await ctx.send(f"Ungültiger Index")
else:
await ctx.send("Command {cmd} nicht vorhanden!")
@help(
category="textcommands",
brief="Entfernt einen Text oder ein gesamtes Text-Kommando.",
syntax="!commands remove <cmd> <id?>",
example="!command remove !command 0",
description="Entfernt den Text des angegebenen Text-Kommandos an entsprechendem Index. War das der einzige Text für dieses Text-Kommando, wird das gesamte Kommando entfernt. Wird kein Index übergeben, so wird ebenfalls das gesamte Text-Kommando entfernt.",
parameters={
"cmd": "Name des zu entfernenden Kommandos (z. B. !horoskop). ",
"id": "*(optional)* Id des zu löschenden Texts"
},
mod=True
)
@cmd_commands.command(name="remove")
@commands.check(utils.is_mod)
async def cmd_command_remove(self, ctx, cmd, id=None):
texts = self.text_commands.get(cmd).get('data')
if texts:
if id: # checkt erst, ob man lediglich einen Eintrag (und nicht das ganze Command) löschen möchte
i = int(id)
if 0 <= i < len(texts): # schließt Aufrufe von Indizen aus, die außerhalb des Felds wären
del texts[i]
await ctx.send(f"Text {i} für Command {cmd} wurde erfolgreich entfernt")
if len(texts) == 0:
self.text_commands.pop(cmd)
self.save_text_commands()
else:
await ctx.send(f"Ungültiger Index")
else: # jetzt kommt man zum vollständigen command removal (ursprünglich "remove-text-command")
# Hier könnte eine Bestätigung angefordert werden (Möchtest du wirklich das Command vollständig löschen? 👍👎)
if cmd in self.text_commands:
self.text_commands.pop(cmd)
remove_help_for(re.sub(r"^!", "", cmd))
await ctx.send(f"Text Command {cmd} wurde erfolgreich entfernt.")
self.save_text_commands()
else:
await ctx.send(f"Text Command {cmd} nicht vorhanden!")
else:
await ctx.send("Command {cmd} nicht vorhanden!")
@cmd_commands.command(name="edit-help")
@commands.check(utils.is_mod)
async def cmd_command_edit_help(self, ctx, cmd, help_message):
help_object = None
try:
cmd = re.sub(r"^!*", "!", cmd)
help_object = self.text_commands.get(cmd).get('help')
except:
pass
if not help_object:
self.text_commands[cmd]['help'] = {}
help_object = self.text_commands[cmd]['help']
help_object['brief'] = help_message
text_command_help(cmd, brief=help_message, category=help_object.get('category'))
self.save_text_commands()
await ctx.send(f"[{cmd}] => Hilfe [{help_message}] erfolgreich hinzugefügt.")
@cmd_commands.command(name="edit-category")
@commands.check(utils.is_mod)
async def cmd_command_edit_category(self, ctx, cmd, category):
help_object = None
try:
help_object = self.text_commands.get(re.sub("^!*", "!", cmd)).get('help')
except:
pass
if not help_object:
help_object = {}
help_object['category'] = category
text_command_help(cmd, category=category, brief=help_object.get('brief'))
self.save_text_commands()
await ctx.send(f"[{cmd}] => Erfolgreich auf Kategorie [{category}] geändert.")
async def list_commands(self, ctx, cmd=None):
if cmd and not self.text_commands.get(cmd):
await ctx.send(f"{cmd} ist kein verfügbares Text-Command")
return
answer = f"Text Commands:\n" if cmd is None else f"Für {cmd} hinterlegte Texte:\n"
cmd_list = list(self.text_commands.keys()) if cmd is None else self.text_commands.get(cmd).get('data')
for i in range(len(cmd_list)):
text = cmd_list[i]
if len(answer) + len(text) > 2000:
await ctx.send(answer)
answer = f""
answer += f"{i}: {text}\n"
await ctx.send(answer)
async def add_command(self, cmd, text, help_message=None, category=None):
mod_channel = await self.bot.fetch_channel(self.mod_channel_id)
command = self.get_or_init_command(cmd)
texts = command.get("data")
texts.append(text)
if help_message and not command.get("help"):
command["help"] = {"brief": help_message}
if category:
command.get("help")["category"] = category
await mod_channel.send(f"[{cmd}] => [{text}] erfolgreich hinzugefügt.")
self.save_text_commands()
async def suggest_command(self, ctx, cmd, text, help_message=None, category=None):
mod_channel = await self.bot.fetch_channel(self.mod_channel_id)
command = self.text_commands.get(cmd)
title = "Vorschlag für neuen Command Text" if command else "Vorschlag für neues Command"
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
description=f"<@!{ctx.author.id}> hat folgenden Vorschlag eingereicht.\n"
f"👍 um den Vorschlag anzunehmen\n"
f"👎 um den Vorschlag abzulehnen")
embed.add_field(name="\u200b", value="\u200b")
embed.add_field(name="Command", value=f'{cmd}', inline=False)
embed.add_field(name="Text", value=f'{text}', inline=False)
if help_message:
embed.add_field(name="Hilfetext", value=f'{help_message}', inline=False)
if category:
embed.add_field(name="Kategorie", value=f'{category}', inline=False)
message = await mod_channel.send(embed=embed)
await message.add_reaction("👍")
await message.add_reaction("👎")
await utils.send_dm(ctx.author,
"Dein Vorschlag wurde den Mods zur Genehmigung vorgelegt. "
"Sobald darüber entschieden wurde, erhältst du eine Benachrichtigung.")
def get_or_init_command(self, cmd):
if command := self.text_commands.get(cmd):
return command
self.text_commands[cmd] = {"data": []}
return self.text_commands.get(cmd)
async def handle_command_reaction(self, message, approved=True):
embed = message.embeds[0]
fields = {field.name: field.value for field in embed.fields}
cmd = fields.get("Command")
text = fields.get("Text")
help_message = fields.get("Hilfetext")
category = fields.get("Kategorie")
member = await message.guild.fetch_member(embed.description[3:21])
if approved:
await self.add_command(cmd, text, help_message=help_message, category=category)
await utils.send_dm(member,
f"Herzlichen Glückwunsch, dein Vorschlag für {cmd} wurde angenommen:\n{text}")
else:
await utils.send_dm(member,
f"Vielen Dank, dass du dir Gedanken darüber machst, wie man 🌱root mit neuen Textkommandos noch nützlicher für alle machen kann.\n" \
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
f"Es können allerdings nicht alle Einreichungen angenommen werden, weswegen dein Vorschlag für {cmd} leider abgelehnt wurde:\n{text}\n" \
f"Eine Vertreterin des Mod-Teams wird sich in Kürze mit dir in Verbindung setzen und dir erklären, was die Beweggründe der Ablehnung sind.")
await message.delete()
@commands.Cog.listener()
async def on_raw_reaction_add(self, payload):
if payload.user_id == self.bot.user.id:
return
if payload.emoji.name in ["👍", "👎"] and payload.channel_id == self.mod_channel_id:
channel = await self.bot.fetch_channel(payload.channel_id)
message = await channel.fetch_message(payload.message_id)
if len(message.embeds) > 0 and message.embeds[0].title in ["Vorschlag für neuen Command Text",
"Vorschlag für neues Command"]:
await self.handle_command_reaction(message, approved=(payload.emoji.name == "👍"))
async def cog_command_error(self, ctx, error):
await handle_error(ctx, error)
@commands.Cog.listener(name="on_message")
async def process_text_commands(self, message):
if message.author == self.bot.user:
return
cmd = message.content.split(" ")[0]
cmd_object = self.text_commands.get(cmd)
if cmd_object:
texts = cmd_object.get('data')
if texts:
await message.channel.send(random.choice(texts))