-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.py
375 lines (315 loc) · 20.2 KB
/
main.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
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
232
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
273
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
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
'''
▓▓▓██▓▓▓▓▓▓ ▓█▓▓▓▓▓▓▓▓▓
█▓▓▓▓▓▓▓█▓▓ ▓▓█▓▓▓▓▓▓▓█
█▓██▓█▓▓█ █▓▓█▓██▓█
▓▓▓▓▓▓▓█ █ █ █▓▓▓▓▓▓▓
▓▓▓▓▓▓███████████▓▓▓▓▓▓
██▒███████████████████▒██
█▓█▒▒█████████████████▒▒█▓█
█████▓▒▒▒█▓░███████████░██▒▒▒▓█████
██████████░░▒░░███████░░▒░░███████████
██ ██████░░░░░░░░░███████░░░░░░░░░▓██████ ██
████▓█ ███████░░░░░█▓▓▓█░░░█████▒░░█▓▓▓█░░░░░████████ █▓████
█████▓██████████░░░░█▓░░░░░░░░░░░░███░░░░░░░░░░░░▓█░░░░▒████████▓▓█████
█▓██████░░░░░░░░░░░░░▓███████▒░░▒█░█▓░░▒███████▓░▓░░░░░░░░░░░██████▓█
██████████░░██░░███░▓▓█▓▓██▓█░░░░░░░░░█▓██▓▓█▓▓░███░░██░░██████████
█ ██████████████▓▓▓▓██░░██░▓░░░▓░██░░██▓▓▓▓██████████████ █
███████████░░░░░░░░░▓░░▒▒▓░░▒░░░░░░░░░███████████
███████░░░░░░░░░░░█▒▒▒█░░░░░░░░░░░███████
█████░░░░░▓░░░░██░██▒░░░▓░░░░░█████
████████░░░░░░▒▒░░░░░░░▒▒░░░░░░████████
██████░░░░░░░▓░░░░░▓░░░░░░░██████
████████░░░░░░░░░░░░░░░░░░░████████
███ █████░░░▒░░░▒░▒░░░▒░░▒█████ ███
█ ██████░░░░░░░░░░░░░███████ █
██ ██ █░░░░░█ ██ ██
<< Czerwony Smok >>
main.py
Hejka, to ja Theri!
Opowiem wam historię.
Pewnego dnia wpadłem na pomysł zrobienia bota dla serwera Red Eye Dragon.
Takiego fajnego żeby można było się nim bawić, czaisz?
Zrealizowałem to 21 listopada 2024 roku, używając moich umiejętności nabytych rok wcześniej
podczas robienia botów "SliztBot" i "Cringeball"
Szczególne podziękowania są dla następujących osób:
Seth - pomysł na komende dyskryminacja i pomoc w testowaniu bota :3
Avalon - Inspiracja przy komendzie dyskryminacja
Meteor i Fotien - bez serwera bot by nie powstał
Oliwier - nie wydał tajemnicy podczas powstawania bota
Kod bota jest w całości dostępny online! Komentarze w kodzie pozwolą przeglądającemu go zrozumieć.
https://github.com/theridev/CzerwonySmokBot
'''
# Zaimportuj moduły: API Discorda i random używany do wybierania losowych rzeczy. Także requests dla pobrania wybranego zdjęcia.
import discord, random, requests
from discord.ext import commands
from discord.ui import Modal
from io import BytesIO
import stats.stats
# Pillow dla stópek :3
from PIL import Image
# Uprawnienia dla bota
intents = discord.Intents.default()
intents.message_content = True
intents.members = True
# Ustaw aktywność oraz zdefiniuj bota
activity = discord.Activity(type=discord.ActivityType.watching, name="Serwer Red Eye Dragon")
bot = commands.Bot(command_prefix="%", activity=activity, status=discord.Status.online, intents=intents, help_command=None)
# Guziki dla wiadomości w komendzie dyskryminacja.
class Buttons(discord.ui.View):
def __init__(self, *, timeout=180): # Guziki przestaną działać po 3 minutach od wysłania wiadomości
super().__init__(timeout=timeout)
# Guziki i wiadomości wysyłane po ich naciśnięciu
@discord.ui.button(label="Dyskryminacja z powodu braku Fursuita.", style=discord.ButtonStyle.blurple, emoji="🚫")
async def blurple_button(self, interaction: discord.Interaction, button: discord.ui.Button):
await interaction.response.send_message(
"Jak możesz nie mieć fursuita! Jeżeli jeszcze nie wiedziałeś - sprawia to że jesteś gorszy! "
"Powinieneś no nie wiem, żyć z poczuciem że jesteś gorszy od osób które mają fursuita."
)
@discord.ui.button(label="Dyskryminacja z powodu posiadania Fursuita.", style=discord.ButtonStyle.green, emoji="🦊")
async def gray_button(self, interaction: discord.Interaction, button: discord.ui.Button):
await interaction.response.send_message(
"Aha, masz fursuita? Jakiego? Pewnie ubierasz się w plastikową torebkę z biedronki i mówisz że masz fursuit. "
"Dobra - a dbasz o ten fursuit? No właśnie. Pewnie cały jest wygnieciony a sama postać która pewnie miała "
"przedstawiać twoją, tfu, fursonę - Jest łysa bo nie umiesz nawet dbać o twój cholerny fursuit!!"
)
@discord.ui.button(label="Dyskryminacja z powodu bycia na serwerze.", style=discord.ButtonStyle.gray, emoji="🐉")
async def green_button(self, interaction: discord.Interaction, button: discord.ui.Button):
await interaction.response.send_message("Co? Jesteś na serwerze Red Eye Dragon? I co? Mam cię dyskryminować? No, zapomnij. Jeżeli nie będziesz sprawiał żadnych dram, lub nie jesteś antifurem pod przykrywką, życzę ci miłej zabawy na serwie :3")
@discord.ui.button(label="Dyskryminacja z powodu bycia dyskryminowanym.", style=discord.ButtonStyle.red, emoji="🛡️")
async def red_button(self, interaction: discord.Interaction, button: discord.ui.Button):
await interaction.response.send_message("Jesteś dyskryminowany? I co? Twój problem. Może dobrze, że się czujesz gorszy. A może rozumiesz, że wszystko co ten bot pisze jest żartem. Nie obwiniajcie Theriego, to Seth chciał mieć taką funkcję w bocie.")
# Dla testowania: Kiedy bot się zaloguje, wyświetl wiadomość w konsoli
@bot.event
async def on_ready():
print(f'Bot zalogowany: {bot.user}!')
# W przypadku wiadomości sprawdź czy wywołuje ona bota. Nie pozwól botu żeby mógł sam wywoływać u siebie komendy.
@bot.event
async def on_message(message):
if message.author == bot.user:
return
# Gdy bot zostanie spingowany, wyświetl wiadomość pomocy. Funkcja chwilowo niedziałająca.
# if bot.user.mentioned_in(message):
# await help(bot)
await bot.process_commands(message)
# POMOCYYYY
@bot.command()
async def help(ctx):
embed=discord.Embed(color=0x99c1f1)
embed.add_field(name="<< Już na pomoc! >>", value=" ", inline=False)
embed.add_field(name=" ", value=" ", inline=False)
embed.add_field(name=r"%mem", value="Wyślij serwerowy mem!", inline=True)
embed.add_field(name=r"%cytat", value="Wyślij serwerowy cytat!", inline=True)
embed.add_field(name=r"%help", value="Wyślij tą wiadomość.", inline=True)
embed.add_field(name=r"%dyskryminacja", value="Doświadcz dyskryminacji!", inline=True)
embed.add_field(name=r"%zgaduj", value="Zgadnij co to za członek serwera!", inline=True)
embed.add_field(name=r"%stopy", value="Dodaj stópki do swojego profilowego! (Sponsorowane przez kult stópek)", inline=True)
embed.add_field(name=r"%lysejadro", value="Dodaj łysego do swojego profilowego! (Sponsorowane przez kult Łysego Jądra)", inline=True)
embed.add_field(name=r"%rank", value="Sprawdź ile razy zgadłeś.", inline=True)
embed.add_field(name=r"%top", value="Sprawdź kto zgadł najwięcej razy!", inline=True)
embed.add_field(name=r"%lysy", value="Wyślij łysego! (Sponsorowane przez kult Łysego Jądra)", inline=True)
embed.add_field(name="Wkrótce więcej!", value=" ", inline=True)
await ctx.send(embed=embed)
# Mem: losowe zdjęcie z kanału memy-serwerowe
@bot.command()
async def mem(ctx):
await losowezdj(ctx, 1308069405351088221, "Mem")
# Cytat: losowe zdjęcie z kanału cytaty-serwerowe
@bot.command()
async def cytat(ctx):
await losowezdj(ctx, 1295872408636358726, "Cytat")
# Lysy: Losowe zdjęcie jondra
@bot.command()
async def lysy(ctx):
await losowezdj(ctx, 1302417266960236606, "Łysy")
# Zostań zdyskryminowany. Zdjęcie losowe. Na pomysł komendy wpadł Seth. Nie obwiniajcie mnie!
@bot.command()
async def dyskryminacja(ctx):
embed=discord.Embed(title=" ", description="Wybierz rodzaj dyskryminacji!", color=0xff7800)
embed.set_image(url="https://radio.bobola.church/wp-content/uploads/2023/07/maxresdefault1.jpg")
await ctx.channel.send(embed=embed,view=Buttons())
# Wybierz losowe zdjęcie z danego kanału
async def losowezdj(ctx, channel, co):
channel = bot.get_channel(channel) # Wybierz kanał podany w argumencie 'channel'
if not channel: # Jeżeli kanał nie istnieje (mało prawdopodobne) wyświetl błąd i zakończ wykonywanie funkcji
embed=discord.Embed(color=0xe01b24)
embed.add_field(name="Błąd!", value="Wybrany kanał nie istnieje!", inline=True)
embed.set_footer(text="Oznacz użytkownika @theridev, żeby spojrzał na ten błąd.") # Zajmę się tym za rok lub dwa.
await ctx.send(embed=embed)
return
return
# Pobierz wiadomości z kanału.
try:
messages = []
async for msg in channel.history(limit=None): # Brak limitu na wiadomości może być ogromnym problemem. YOLO.
messages.append(msg)
except discord.Forbidden: # Błąd 403 - Forbidden / Zabroniony. Forbidden to najgorszy album Black Sabbath, tyle wiem.
embed=discord.Embed(color=0xe01b24)
embed.add_field(name="Błąd!", value="Bot nie ma uprawnień żeby odczytywać wiadomości na tym kanale!", inline=True)
embed.set_footer(text="Oznacz użytkownika @theridev, żeby spojrzał na ten błąd.") # Zajmę się tym za rok lub dwa.
await ctx.send(embed=embed)
return
# Przefiltruj wiadomości żeby znaleźć zdjęcia.
image_messages = [
msg for msg in messages if msg.attachments and msg.attachments[0].content_type.startswith("image")
]
# Nie wykryto zdjęć!
if not image_messages:
embed=discord.Embed(color=0xe01b24)
embed.add_field(name="Błąd!", value="Nie można było wykryć zdjęć na danym kanale.", inline=True)
embed.set_footer(text="Oznacz użytkownika @theridev, żeby spojrzał na ten błąd.")
await ctx.send(embed=embed)
return
# Wybierz losowe zdjęcie i wyślij je wraz z ładniutką wiadomością :3
random_message = random.choice(image_messages)
random_image = random_message.attachments[0]
# Utwórz embed z osadzonym obrazkiem
embed = discord.Embed(color=0x8ff0a4)
embed.add_field(name="%s serwerowy!" % co, value=f"Wysłany przez {random_message.author.display_name}.", inline=True)
embed.set_image(url=random_image.url) # Osadź obrazek w embed
await ctx.send(embed=embed)
# Guziki dla komendy zgaduj.
class zgadujGuziki(discord.ui.View):
def __init__(self, guess_user, guess_user_display, *, timeout=180): # Po trzech minutach od wysłania wiadomości guziki staną się nieaktywne.
super().__init__(timeout=timeout)
self.guess_user = guess_user
self.guess_user_display = guess_user_display
@discord.ui.button(label="Zgaduj", style=discord.ButtonStyle.red)
async def confirm(self, interaction: discord.Interaction, button: discord.ui.Button):
await interaction.response.send_modal(Questionnaire(self.guess_user, self.guess_user_display))
# Kwestionarz! Pozwala on na zgadywanie użytkownika.
class Questionnaire(Modal, title='Zgadywanka'):
name = discord.ui.TextInput(label='Co to za użytkownik?')
def __init__(self, guess_user, guess_user_display, *args, **kwargs):
super().__init__(*args, **kwargs)
self.guess_user = guess_user
self.guess_user_display = guess_user_display
async def on_submit(self, interaction: discord.Interaction):
guessOG = self.name
guessLowercase = str(guessOG).lower()
# zadziała np i THERI i theri i Theri i THeRi...
guessUserDisplayLowercase = str(self.guess_user_display).lower()
# Sprawdź czy użytkownik trafił albo na poprawną nazwę wyświetleniową albo na poprawną nazwę użytkownika.
# Np: i "theri" i "theridev" zadziała.
if guessLowercase == self.guess_user.lower() or guessLowercase == guessUserDisplayLowercase or guessLowercase == "kastracja" and self.guess_user.lower() == "postal_dude_jr."or guessLowercase == "dyskryminacja" and self.guess_user.lower() == "dmnk_dsc":
embed = discord.Embed(color=0x8ff0a4)
embed.add_field(name="Zgadłeś! Użytkownik to %s" % self.guess_user, value=" ", inline=True)
stats.stats.add(interaction.user.name, 1)
await interaction.response.send_message(embed=embed)
else:
# ups
embed = discord.Embed(color=0xe01b24)
embed.add_field(name=f"Źle! Ten użytkownik to nie {guessLowercase}", value=" ", inline=True)
await interaction.response.send_message(embed=embed)
# Zgaduj!
@bot.command()
async def zgaduj(ctx):
global guessUser
global guessUserDisplay
users = ctx.guild.members # Lista wszystkich uczestników serwera
user = random.choice(users) # Wybierz losowego użytkownika. Boty - niestety - też sie liczą. Do naprawienia...?
guessUser = user.name # Nazwa użytkownika
guessUserDisplay = user.display_name # Nazwa wyświetlana
pfp = user.avatar.url # URL awataru, do zgadywanki.
# Wiadomość!
embed = discord.Embed(title=" ", description="Kto to?", color=0x8ff0a4)
embed.set_author(name="Co to za użytkownik?")
embed.set_image(url=pfp)
await ctx.send(embed=embed, view=zgadujGuziki(guess_user=guessUser, guess_user_display=guessUserDisplay)) # Send message to the channel
@bot.command()
async def stopy(ctx):
invoker = ctx.author
invokerPFPUrl = invoker.avatar.url
# Pobierz awatar użytkownika za pomocą requests
response = requests.get(invokerPFPUrl, headers={"User-Agent": "Mozilla/5.0"})
if response.status_code == 200:
invokerPFP = Image.open(BytesIO(response.content)).convert("RGBA") # musi być RGBA!!!
stopy = Image.open("stopki.png").convert("RGBA") # musi być RGBA!!!
# Żeby poprawnie funkcja działała oba zdjęcia powinny być w tym samym rozmiarze.
invokerResized = invokerPFP.resize((500, 500))
stopyResized = stopy.resize((500, 500))
# Puste zdjęcie
final_image = Image.new("RGBA", (500, 500))
final_image.paste(invokerResized, (0, 0)) # Pierwsze zdjęcie
final_image.paste(stopyResized, (0, 0), stopyResized) # Nakładka!
# Przekonwertuj do RGB dla większej kompatybilności, nigdy nie wiadomo
final_image_rgb = final_image.convert("RGB")
# Save and send the json_object[user] + value image
with BytesIO() as image_binary:
final_image_rgb.save(image_binary, "PNG")
image_binary.seek(0)
final = discord.File(fp=image_binary, filename="image.png")
embed = discord.Embed(color=0x8ff0a4)
embed.add_field(name="Stópki!", value=" ", inline=True)
embed.set_image(url="attachment://image.png")
await ctx.send(file=final, embed=embed)
else:
embed = discord.Embed(color=0xe01b24)
embed.add_field(name="Błąd!", value="Nie udało się pobrać awataru użytkownika!", inline=True)
embed.set_footer(text="Oznacz użytkownika @theridev, żeby spojrzał na ten błąd.")
await ctx.send(embed=embed)
@bot.command()
async def lysejadro(ctx):
invoker = ctx.author
invokerPFPUrl = invoker.avatar.url
# Pobierz awatar użytkownika za pomocą requests
response = requests.get(invokerPFPUrl, headers={"User-Agent": "Mozilla/5.0"})
if response.status_code == 200:
invokerPFP = Image.open(BytesIO(response.content)).convert("RGBA") # musi być RGBA!!!
lysy = Image.open("lysy.png").convert("RGBA") # musi być RGBA!!!
# Żeby poprawnie funkcja działała oba zdjęcia powinny być w tym samym rozmiarze.
invokerResized = invokerPFP.resize((500, 500))
lysyResized = lysy.resize((500, 500))
# Puste zdjęcie
final_image = Image.new("RGBA", (500, 500))
final_image.paste(invokerResized, (0, 0)) # Pierwsze zdjęcie
final_image.paste(lysyResized, (0, 0), lysyResized) # Nakładka!
# Przekonwertuj do RGB dla większej kompatybilności, nigdy nie wiadomo
final_image_rgb = final_image.convert("RGB")
# Save and send the image
with BytesIO() as image_binary:
final_image_rgb.save(image_binary, "PNG")
image_binary.seek(0)
final = discord.File(fp=image_binary, filename="lysy.png")
embed = discord.Embed(color=0x8ff0a4)
embed.add_field(name="ŁYSYYYYY!", value=" ", inline=True)
embed.set_image(url="attachment://lysy.png")
await ctx.send(file=final, embed=embed)
else:
embed = discord.Embed(color=0xe01b24)
embed.add_field(name="Błąd!", value="Nie udało się pobrać awataru użytkownika!", inline=True)
embed.set_footer(text="Oznacz użytkownika @theridev, żeby spojrzał na ten błąd.")
await ctx.send(embed=embed)
@bot.command()
async def rank(ctx):
invoker = ctx.author
invokerName = ctx.author.name
randomColor = random.randrange(0, 2**24)
randomHex = hex(randomColor)
randomHexINT = int(randomHex,16)
value = stats.stats.getUserValue(invokerName)
if value == 1:
raz = "raz"
else:
raz = "razy"
embed = discord.Embed(color=randomHexINT)
embed.add_field(name="Użytkownik %s zgadł %s %s!" % (invokerName, str(value), raz), value=" ", inline=True)
embed.set_image(url=ctx.author.avatar.url) # Awatar Jupii
await ctx.send(embed=embed)
@bot.command()
async def top(ctx):
topValues = stats.stats.getAllValues()
top = {k: v for k, v in sorted(topValues.items(), key=lambda item: item[1], reverse=True)}
randomColor = random.randrange(0, 2**24)
randomHex = hex(randomColor)
randomHexINT = int(randomHex,16)
embed = discord.Embed(color=randomHexINT)
for x, (user, value) in enumerate(top.items(), start=1):
if value == 1:
raz = "raz"
else:
raz = "razy"
embed.add_field(name=f"{x}. {user}", value=f"Zgadnął {value} {raz}.")
await ctx.send(embed=embed)
# Token poniżej. Ze względów bezpieczeństwa jest on przechowywany w oddzielnym pliku, nie zapisywanym przez Git.
with open(".token", "r") as token_file:
bot.run(token_file.read().strip())