forked from NozyZy/Le-ptit-bot
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbot.py
More file actions
executable file
·3845 lines (3347 loc) · 155 KB
/
Copy pathbot.py
File metadata and controls
executable file
·3845 lines (3347 loc) · 155 KB
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
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
# Standard library imports
import argparse
import asyncio
import io
import json
import logging
import math
import os
import random
import re
import time
import time as time_module
import typing
from collections import defaultdict
from datetime import date
import Tyradex
# Third-party imports
import discord
import requests
from PIL import Image, ImageDraw, ImageFont
from bs4 import BeautifulSoup
from discord.ext import commands
from dotenv import load_dotenv
# Local application imports
from fonctions import (
crypting,
equal_games,
facto,
finndAndReplace,
is_prime,
nbInStr,
strToInt,
verifAlphabet,
)
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger()
# Disable debug logs from urllib3 and requests
logging.getLogger('urllib3').setLevel(logging.WARNING)
logging.getLogger('requests').setLevel(logging.WARNING)
load_dotenv()
# ID : 653563141002756106
# https://discordapp.com/oauth2/authorize?&client_id=653563141002756106&scope=bot&permissions=8
parser = argparse.ArgumentParser(
prog='Le p\'tit bot',
description='Shitty bot',
epilog='💥💥💥')
parser.add_argument('-d', '--dev',
action='store_true')
args = parser.parse_args()
intents = discord.Intents.all()
intents.members = True
client = discord.Client(intents=intents)
bot = commands.Bot(command_prefix="--",
description="Le p'tit bot !",
case_insensitive=True,
intents=intents)
with open("txt/tg.txt", "r+") as tgFile:
nbtg: int = int(tgFile.readlines()[0])
nbprime: int = 0
with open("txt/sexe.txt", "r", encoding="utf-8") as sexeFile:
sexe_words = sexeFile.read().split("\n")
sexe_words = [w for w in sexe_words if w]
# Locks to protect global variables from race conditions
nbtg_lock = asyncio.Lock()
nbprime_lock = asyncio.Lock()
# Rate limiting system
# Track last usage time for each user (user_id -> last_use_timestamp)
user_cooldowns = defaultdict(float)
# Tracking of "god" requests per user per day
# Format: {user_id: {"date": "YYYY-MM-DD", "count": int}}
god_requests = {}
# Tracking of sexe word usage per user per day
# Format: {user_id: {"date": "YYYY-MM-DD", "count": int}}
sexe_requests = {}
# List of all Pokémon names
ALL_POKEMONS = []
POKEMON_CACHE_FILE = "data/pokemon_cache.json"
def check_cooldown(user_id: int, cooldown_seconds: float = 2.0) -> bool:
"""
Checks whether a user can perform an action.
Returns True if the action is allowed, False if it is on cooldown.
"""
current_time = time_module.time()
last_use = user_cooldowns[user_id]
if current_time - last_use >= cooldown_seconds:
user_cooldowns[user_id] = current_time
return True
return False
# Load server names from file
def load_server_names():
try:
with open("txt/server_names.txt", "r") as f:
lines = f.readlines()
names = {}
for line in lines:
if ":" in line:
server_id, name = line.strip().split(":", 1)
names[server_id] = name
return names
except FileNotFoundError:
return {}
# Save server names to file
def save_server_names(server_names):
with open("txt/server_names.txt", "w") as f:
for server_id, name in server_names.items():
f.write(f"{server_id}:{name}\n")
server_names = load_server_names()
# Load OneCOPS counter from file
def load_onecops_counter():
try:
with open("txt/onecops_counter.txt", "r") as f:
return int(f.read().strip())
except (FileNotFoundError, ValueError):
return 0
# Save OneCOPS counter to file
def save_onecops_counter(count):
with open("txt/onecops_counter.txt", "w") as f:
f.write(str(count))
# Load sexe stats from file
def load_sexe_stats():
try:
with open("data/sexe_stats.txt", "r") as f:
stats = {}
for line in f:
if line.strip():
parts = line.strip().split(":")
if len(parts) == 3:
user_id, date, size = parts
if user_id not in stats:
stats[user_id] = []
stats[user_id].append({"date": date, "size": int(size)})
return stats
except FileNotFoundError:
return {}
# Save sexe stats to file
def save_sexe_stats(stats):
os.makedirs("data", exist_ok=True)
with open("data/sexe_stats.txt", "w") as f:
for user_id, entries in stats.items():
for entry in entries:
f.write(f"{user_id}:{entry['date']}:{entry['size']}\n")
# Sexe stats history per user
# Format: {user_id: [{"date": "YYYY-MM-DD", "size": int}, ...]}
sexe_stats = load_sexe_stats()
# Load Pokémon cache from file
def load_pokemon_cache():
try:
with open(POKEMON_CACHE_FILE, "r", encoding="utf-8") as f:
cache = json.load(f)
logger.info(f"Fetched {len(cache)} pokémon from cache")
return cache
except:
logger.error("Failed to load pokemon cache")
return []
# Save Pokémon cache to file
def save_pokemon_cache(data):
os.makedirs("data", exist_ok=True)
with open(POKEMON_CACHE_FILE, "w", encoding="utf-8") as f:
json.dump(data, f)
# Build Pokepedia URL for a given Pokémon name + mega + forms handling
def build_pokepedia_url(pokemon_name: str) -> str:
base_name = pokemon_name.lower()
return f"https://www.pokepedia.fr/" + base_name
# French month names
FRENCH_MONTHS = [
"janvier", "février", "mars", "avril", "mai", "juin",
"juillet", "août", "septembre", "octobre", "novembre", "décembre"
]
GUILD_IDS = [
410766134569074691,
1193546302970146846,
1420660433722802188,
826575187721322546,
1457146663331303568
]
# On ready message
@bot.event
async def on_ready():
global ALL_POKEMONS
await bot.change_presence(activity=discord.Game(
name=f"insulter {nbtg} personnes"))
logger.info("Logged in as")
if bot.user:
logger.info(bot.user.name)
logger.info(bot.user.id)
if args.dev:
logger.info("Synchronizing slash commands for guilds :")
for guild_id in GUILD_IDS:
guild = discord.Object(id=guild_id)
try:
await bot.tree.sync(guild=guild)
logger.info(f"\t- {guild_id}")
except Exception as e:
logger.info(f"\t- Failed for {guild_id}, reason : {e}")
else:
logger.info("Synchronizing slash commands...")
try:
await bot.tree.sync()
except Exception as e:
logger.warning(f"Failed syncing, reason : {e}")
logger.info("------")
# Apply saved names to servers
for guild in bot.guilds:
if str(guild.id) in server_names:
try:
await guild.me.edit(nick=server_names[str(guild.id)])
logger.info(f"Applied saved name '{server_names[str(guild.id)]}' to server {guild.name}")
except discord.Forbidden:
logger.warning(f"No permission to change nickname in server {guild.name}")
try:
# Get total count of pokemons from API
all_tyradex = Tyradex.Pokemon.all()
api_count = len(all_tyradex)
cached_pokemons = load_pokemon_cache()
# Check if cache is outdated => don't have the last pokemons
if len(cached_pokemons) != api_count:
logger.info(f"Cache Pokémon obsolète → mise à jour ({len(cached_pokemons)} => {api_count})")
ALL_POKEMONS = [
{
"name": getattr(p.name, "fr", "Inconnu"),
"id": getattr(p, "pokedex_id", 0),
"image": getattr(p.sprites, "regular", None),
"shiny_image": getattr(p.sprites, "shiny", None),
"type": p.types[0].name.lower() if p.types else "unknown"
}
for p in all_tyradex
]
save_pokemon_cache(ALL_POKEMONS)
logger.info(f"Cache mis à jour ({len(ALL_POKEMONS)} pokémons)")
else:
logger.info("Cache Pokémon à jour.")
ALL_POKEMONS = cached_pokemons
except Exception as e:
logger.error(f"Erreur preload : {e}")
# fallback sécurité
ALL_POKEMONS = load_pokemon_cache()
if not ALL_POKEMONS:
logger.critical("Aucun cache Pokémon disponible !")
# Error handler for command cooldowns
@bot.event
async def on_command_error(ctx, error):
if isinstance(error, commands.CommandOnCooldown):
remaining = int(error.retry_after)
await ctx.send(f"⏳ Cette commande est en cooldown. Réessaie dans {remaining} seconde{'s' if remaining > 1 else ''}.")
elif isinstance(error, commands.MissingRequiredArgument):
await ctx.send(f"❌ Argument manquant : `{error.param.name}`")
elif isinstance(error, commands.BadArgument):
await ctx.send(f"❌ Argument invalide. Vérifie la syntaxe de la commande.")
else:
# Log other errors without sending to user
logger.error(f"Command error: {error}")
# Get every message sent, stocked in 'message'
@bot.event
async def on_message(message):
global nbtg
global nbprime
global ALL_POKEMONS
channel = message.channel
MESSAGE = message.content.lower()
rdnb = random.randint(1, 5)
today = date.today()
day = today.strftime("%d")
month = today.strftime("%m")
year = today.strftime("%y")
user = message.author
# Ignore code blocks
if "```" in MESSAGE:
return
if message.author == bot.user: # we don't want the bot to repeat itself
return
if message.author.bot: return
with open("txt/bans.txt", "r+") as bansFile:
bansLines = bansFile.read().split('\n')
if str(channel.id) in bansLines: # option to ban reactions from some channels
await bot.process_commands(message)
return
# open and stock the dico, with a lot of words
with open("txt/dico.txt", "r+", encoding="utf-8") as dicoFile:
dicoLines = dicoFile.readlines()
dicoSize = len(dicoLines)
# expansion of the dico, with words of every messages (stock only words, never complete message)
# we don't want a specific bot (from a friend) to expand the dico => don't know who but it's ok ^^
if message.author.id != 696099307706777610 and not MESSAGE.startswith("--"):
# Split message into words
words = MESSAGE.split()
for word in words:
# Remove punctuation but keep apostrophes and alphabetic characters
clean_word = ''.join(c for c in word if c.isalpha() or c in "éèàïøâñîûç'")
clean_word = clean_word.lower().strip()
# Filter valid words: length < 27
# Note: verifAlphabet will reject words with apostrophes, so we skip it for words with apostrophes
if clean_word and len(clean_word) < 27:
if verifAlphabet(clean_word):
word_with_newline = clean_word + "\n"
if word_with_newline not in dicoLines:
logger.info(f"{user.name} - {message.guild.name} - nouveau mot : {clean_word}")
dicoLines.append(word_with_newline)
newDico = sorted(set(dicoLines))
if len(newDico) > dicoSize:
logger.info(f"Saving Dico.... Total words : {len(newDico)}")
with open("txt/dico.txt", "w+", encoding="utf-8") as dicoFile:
dicoFile.writelines(newDico)
# stock file full of insults (yes I know...)
with open("txt/insultes.txt", "r+", encoding="utf-8") as fichierInsulte:
insultes = fichierInsulte.read().split("\n")
# stock file full of branlettes (yes I know...)
with open("txt/branlette.txt", "r") as fichierBranlette:
linesBranlette = fichierBranlette.readlines()
branlette = []
for line in linesBranlette:
line = line.replace("\n", "")
branlette.append(line)
if message.content.startswith("--addInsult"):
mot = ' '.join(MESSAGE.split()[1:])
if len(mot) <= 2:
await channel.send("Sympa l'insulte...")
return
mot = mot + '\n'
with open("txt/insultes.txt", "a") as fichierInsulte:
fichierInsulte.write(mot)
logger.info(f"{user.name} - {message.guild.name} - Nouvelle insulte : {mot}")
await channel.send("Je retiens...")
if message.content.startswith("--addBranlette"):
mot = ' '.join(MESSAGE.split()[1:])
if len(mot) <= 2:
await channel.send("super la Branlette...")
return
if not mot.startswith(("jme", "j'me", "jm'", "je m")):
await channel.send("C'est moi qui ME, alors JME... stp 🍆")
return
mot = mot + '\n'
with open("txt/branlette.txt", "a") as fichierBranlette:
fichierBranlette.write(mot)
logger.info(f"{user.name} - {message.guild.name} - Nouvelle branlette :", mot)
await channel.send("Je retiens...")
# ping a people 10 time, once every 3 sec
if MESSAGE.startswith("--appel"):
if "<@!653563141002756106>" in MESSAGE:
await channel.send("T'es un marrant toi")
logger.info(f"{user.name} - {message.guild.name} - A tenté d'appeler le bot")
elif "<@" not in MESSAGE:
await channel.send(
"Tu veux appeler quelqu'un ? Bah tag le ! *Mondieu...*")
logger.info(f"{user.name} - {message.guild.name} - A tenté d'appeler sans taguer")
elif not message.author.guild_permissions.administrator:
await channel.send("Dommage, tu n'as pas le droit ¯\\_(ツ)_/¯")
logger.info(f"{user.name} - {message.guild.name} - A tenté d'appeler sans les droits")
else:
nom = MESSAGE.replace("--appel ", "")
liste = [
"Allo ",
"T'es la ? ",
"Tu viens ",
"On t'attend...",
"Ca commence a faire long ",
"Tu viens un jour ??? ",
"J'en ai marre de toi... ",
"Allez grouille !! ",
"Toujours en rertard de toute facon... ",
"ALLOOOOOOOOOOOOOOOOOOOOOOOOOO ",
]
random.shuffle(liste)
for mot in liste:
text = mot + nom
await channel.send(text)
await asyncio.sleep(3)
logger.info(f"{user.name} - {message.guild.name} - A appelé {nom}")
return
# if you tag this bot in any message
if bot.user and f"<@{bot.user.id}>" in MESSAGE:
logger.info(f"{user.name} - {message.guild.name} - A ping le bot")
user = str(message.author.nick)
if user == "None":
user = message.author.name
rep = [
"ya quoi ?!",
"Qu'est ce que tu as " + user + " ?",
"Oui c'est moi",
"Présent !",
"*Oui ma bicheuh <3*",
user + " lance un duel.",
"Je t'aime.",
"T'as pas d'amis ? trouduc",
]
if user == "Le Grand bot":
rep.append("Oui bb ?")
rep.append("Yo <@747066145550368789>")
elif message.author.id == 359743894042443776:
rep.append("Patron !")
rep.append("Eh mattez, ce mec est mon dev 👆")
rep.append("Je vais tous vous anéantir, en commençant par toi.")
rep.append("Tu es mort.")
await channel.send(random.choice(rep))
return
# send 5 randoms words from the dico
if MESSAGE == "--random":
logger.info(f"{user.name} - {message.guild.name} - A généré une phrase aléatoire")
text = ""
rd_dico = dicoLines
random.shuffle(rd_dico)
for i in range(5):
text += rd_dico[i]
if i != 4:
text += " "
text += "."
text = text.replace("\n", "")
if text:
text = text[0].upper() + text[1:]
await channel.send(text)
return
# send the number of words stocked in the dico
if MESSAGE == "--dico":
logger.info(f"{user.name} - {message.guild.name} - A compter le nombe de mots du dico")
text = f"J'ai actuellement {str(len(dicoLines))} mots enregistrés, nickel"
await channel.send(text)
return
# rename bot command (admin only)
if MESSAGE.startswith("--rename "):
if not message.author.guild_permissions.administrator:
await channel.send("❌ Seuls les administrateurs peuvent utiliser cette commande.")
return
new_name = message.content[9:] # Remove "--rename "
if len(new_name) > 32:
await channel.send("❌ Le nom ne peut pas dépasser 32 caractères.")
return
if len(new_name) == 0:
await channel.send("❌ Veuillez spécifier un nom. Usage: `--rename NouveauNom`")
return
# block control characters and certain problematic characters ^^
if any(ord(c) < 32 for c in new_name):
await channel.send("❌ Le nom contient des caractères invalides.")
return
# Strip whitespace
new_name = new_name.strip()
if len(new_name) == 0:
await channel.send("❌ Le nom ne peut pas être vide ou composé uniquement d'espaces.")
return
try:
await message.guild.me.edit(nick=new_name)
server_names[str(message.guild.id)] = new_name
save_server_names(server_names)
await channel.send(f"✅ Mon nom a été changé en '{new_name}' sur ce serveur.")
logger.info(f"{user.name} - {message.guild.name} - A renommé le bot en '{new_name}' sur {message.guild.name}")
except discord.Forbidden:
await channel.send("❌ Je n'ai pas la permission de changer mon pseudo sur ce serveur.")
except discord.HTTPException as e:
await channel.send(f"❌ Erreur lors du changement de nom: {e}")
# reset bot name to default (admin only)
if MESSAGE == "--resetname":
if not message.author.guild_permissions.administrator:
await channel.send("❌ Seuls les administrateurs peuvent utiliser cette commande.")
return
try:
await message.guild.me.edit(nick=None)
if str(message.guild.id) in server_names:
del server_names[str(message.guild.id)]
save_server_names(server_names)
await channel.send("✅ Mon nom a été remis par défaut sur ce serveur.")
logger.info(f"{user.name} - {message.guild.name} - A remis le nom par défaut sur {message.guild.name}")
except discord.Forbidden:
await channel.send("❌ Je n'ai pas la permission de changer mon pseudo sur ce serveur.")
except discord.HTTPException as e:
await channel.send(f"❌ Erreur lors du reset du nom: {e}")
return
# begginning of reaction programs, get inspired
if not MESSAGE.startswith("--"):
# Random response for the TQ user with the image allez.png
if user.id == 756178270830985286 and message.guild.id == 1382722391117135904:
tq_rand = random.randint(1, 100)
if tq_rand <= 3: # ~3% ≈ 1/31
logger.info(f"{user.name} - {message.guild.name} - Allez image envoyée TQ")
await channel.send(file=discord.File("images/allez.png"))
elif tq_rand <= 8: # ~5% ≈ 1/20
logger.info(f"{user.name} - {message.guild.name} - Tristan vient d'arriver")
msg = await channel.send("Tristan arrive dans 7 ...")
for i in range(6, 0, -1):
await asyncio.sleep(1)
await msg.edit(content=f"Tristan arrive dans {i} ...")
await asyncio.sleep(1)
await msg.delete()
await channel.send(content="Tristan vient d'arriver.", file=discord.File("images/tq.gif"))
if ("enerv" in MESSAGE or "énerv" in MESSAGE) and rdnb >= 2:
logger.info(f"{user.name} - {message.guild.name} - S'est enervé")
await channel.send("(╯°□°)╯︵ ┻━┻")
if "(╯°□°)╯︵ ┻━┻" in MESSAGE:
logger.info(f"{user.name} - {message.guild.name} - A balancé la table")
await channel.send("┬─┬ ノ( ゜-゜ノ)")
if MESSAGE.strip(".;,?! \"')").endswith("lucas"):
logger.info(f"{user.name} - {message.guild.name} - A dit Lucas (goubet)")
await channel.send("goubet")
if (MESSAGE.startswith("tu sais") or MESSAGE.startswith("vous savez")
or MESSAGE.startswith("savez vous")
or MESSAGE.startswith("savez-vous")
or MESSAGE.startswith("savais-tu")
or MESSAGE.startswith("savais tu")) and rdnb > 3:
logger.info(f"{user.name} - {message.guild.name} - A demandé si on savait")
reponses = [
"J'en ai vraiment rien à faire tu sais ?",
"Waaa... Je bois tes paroles",
"Dis moi tout bg",
"Balec",
"M'en fous",
"Plait-il ?",
]
await channel.send(random.choice(reponses))
if MESSAGE == "pas mal" and rdnb > 2:
logger.info(f"{user.name} - {message.guild.name} - A trouvé ca pas mal")
reponses = ["mouais", "peut mieux faire", "woaw", ":o"]
await channel.send(random.choice(reponses))
if (MESSAGE == "ez" or MESSAGE == "easy") and rdnb >= 3:
logger.info(f"{user.name} - {message.guild.name} - A trouvé ça facile")
reponses = [
"https://tenor.com/view/walking-dead-easy-easy-peasy-lemon-squeazy-gif-7268918",
"https://tenor.com/view/pewds-pewdiepie-easy-ez-gif-9475407",
"https://tenor.com/view/easy-red-easy-button-red-button-gif-4642542",
"https://tenor.com/view/simple-easy-easy-game-easy-life-deal-with-it-gif-9276124",
]
await channel.send(random.choice(reponses))
if MESSAGE in sexe_words:
logger.info(f"{user.name} - {message.guild.name} - A parlé de bite")
# if mention someone
if message.mentions:
# if mention him/herself
if user in message.mentions:
reponses_self_mention = [
"T'es au courant que c'est toi-même que tu ping là ?",
"Mais t'es mal câblé ma parole",
f"Ah parce que tu parles de {MESSAGE}, mais EN PLUS tu parles seul ? Mazette",
"Je sais pas ce qui se passe dans ta tête mais c'est chelou là"
]
await channel.send(random.choice(reponses_self_mention))
return
# if mention someone else
else:
mentioned = message.mentions[0].mention
reponses_other_mention = [
f"Tu demandes vraiment le {MESSAGE.upper()} de quelqu'un là ? Gros pervers",
f"Bah alors ce n'est pas à toi ça 🤨 Pourquoi tu parles de celle de {mentioned} ?",
f"Oh oh oh, {mentioned} c'est pas la tienne hein !",
f"Euh... je crois que {mentioned} apprécierait que tu arrêtes de parler de la sienne",
f"Hé {mentioned}, on parle de toi là apparemment...",
f"{mentioned}, t'as une occasion à saisir là je pense 😏",
f"{mentioned} veux faire paf contre paf avec toi visiblement"
]
await channel.send(random.choice(reponses_other_mention))
return
# Track sexe requests per user per day
current_date = today.strftime("%Y-%m-%d")
if user.id not in sexe_requests or sexe_requests[user.id]["date"] != current_date:
sexe_requests[user.id] = {"date": current_date, "count": 0}
sexe_requests[user.id]["count"] += 1
count = sexe_requests[user.id]["count"]
# Generate dick size for the day 8=D
seed = hash((user.id, today.strftime("%Y-%m-%d")))
random.seed(seed)
max_size = 31
size = random.choices(range(0, max_size+1), weights=[math.exp(-0.07 * i) for i in range(1, max_size+2)])[0]
text = "8" + "=" * size + "D"
bruh = []
file = None
random.seed(None)
if count == 1:
user_id_str = str(user.id)
if user_id_str not in sexe_stats:
sexe_stats[user_id_str] = []
if not any(entry["date"] == current_date for entry in sexe_stats[user_id_str]):
sexe_stats[user_id_str].append({"date": current_date, "size": size})
save_sexe_stats(sexe_stats)
if size == 0:
sexe_images = [
f"images/sexe/{img}" for img in os.listdir("images/sexe/")
if os.path.isfile(f"images/sexe/{img}") and not img.startswith(".")
]
file = discord.File(random.choice(sexe_images))
elif size == max_size:
text += "\n\nAlleeeeeeeezzz, le champion du jour ! 🥳 @tout le monde"
elif count >= 2:
if count >= 6:
bruh = [
"Putain d'obsédé",
"T'as vraiment que ça à faire ?",
"...",
"🤡🤡🤡",
"C'est pas en vérifiant 50 fois que ça va changer",
"Ok je crois t'as compris là",
"Bon allez lâche moi la bite là (*tu l'as ?*)",
"Bizarre votre pote là"
]
bruh += [
"Toujours pareil mec...",
"Ça va pas grandir hein, tu le sais ?",
"T'es sûr que ça va ?",
"Arrête de me casser les couilles, et va faire autre chose",
"Bon ta gueule nan ?",
"C'est marrant ça... le zizi..."
]
text += "\n\n" + random.choice(bruh)
await channel.send(text, file=file)
if re.fullmatch(r"pok[eé]mon[?!\.\s]*", MESSAGE.strip()):
# Save
author = user
# If someone is mentioned, show their Pokemon instead
if message.mentions and user not in message.mentions:
user = message.mentions[0]
if not ALL_POKEMONS:
ALL_POKEMONS = load_pokemon_cache()
day_of_year = today.timetuple().tm_yday
seed = hash((user.id, day_of_year, today.year))
rng = random.Random(seed)
shiny = rng.randint(0, 8192) == 0
pokemon = rng.choice(ALL_POKEMONS)
text = rng.choice([
"En vrai, pas dingue",
"Stylé en sah",
"J'aurai préféré être une barbie à ta place",
"Franchement je suis un peu jaloux",
"Pas de quoi se vanter",
"J'espère pour toi que ce sera mieux demain",
"T'es accro avoue ?"
])
colors = {
"acier": 0x60A2B9,
"combat": 0xFF8100,
"dragon": 0x4F60E2,
"eau": 0x2481EF,
"feu": 0xE72324,
"glace": 0x3DD9FF,
"insecte": 0x92A212,
"normal": 0xA0A2A0,
"tenebres": 0x4F3F3D,
"plante": 0x3DA224,
"poison": 0x923FCC,
"psy": 0xEF3F7A,
"roche": 0xB0AA82,
"sol": 0x92501B,
"spectre": 0x703F70,
"vol": 0x82BAEF,
"electrik": 0xF4D03F,
"fee": 0xF4A7B9,
}
try:
if not ALL_POKEMONS:
logger.error(f"Pokemon cache is empty, cannot load pokemon for user {user.name} ({user.id})")
error_file = discord.File("images/failled.jpg")
await channel.send(file=error_file)
await channel.send("C'est un soucis de cache, appelez-moi un admin immédiatement !")
raise Exception("Pokemon cache not loaded")
embed_color = colors.get(pokemon["type"], 0xFCFCFC)
if user == author:
title = f"Ton Pokémon du jour {'✨' if shiny else ''} !"
description = f"Aujourd'hui, tu es **[{pokemon['name']}]({build_pokepedia_url(pokemon['name'])})** !"
if shiny:
description += "\n✨ ***SHINY*** ✨"
else:
title = f"Pokémon du jour de {user.display_name}"
description = f"Aujourd'hui, {user.mention} est **[{pokemon['name']}]({build_pokepedia_url(pokemon['name'])})** !"
embed = discord.Embed(
title=title,
description=description,
color=discord.Color.gold() if shiny else embed_color
)
embed.set_author(
name=message.guild.me.display_name,
url="https://github.com/NozyZy/Le-ptit-bot",
icon_url=message.guild.me.display_avatar.url,
)
embed.set_thumbnail(url=user.avatar.url)
embed.set_image(url=pokemon["shiny_image"] if shiny else pokemon["image"])
embed.set_footer(
text=f"Pokémon n°{pokemon['id']} | Reviens demain pour découvrir un nouveau Pokémon !"
)
await channel.send(text, embed=embed)
logger.info(
f"{user.name} - {message.guild.name} - A demandé son Pokémon du jour {pokemon['image']} : {pokemon['id']}")
except Exception as e:
logger.error(f"Pokemon error occurred : {e}")
error_file = discord.File("images/failled.jpg")
await channel.send()
await channel.send("C'est un flop, appelez-moi un admin immédiatement!")
await channel.send(
"C'est un flop, appelez-moi un admin immédiatement!\n"
f"- Type: ``{type(e).__name__}``\n"
f"- Détail: ``{str(e)[:100]}``",
file=error_file
)
if MESSAGE == "pouet":
await channel.send("Roooooh ta gueuuuuule putaiiiiin")
if MESSAGE == "poueth":
await channel.send("Poueth poueth !! 🐤")
if (MESSAGE.startswith("stop") or MESSAGE.startswith("arrête")
or MESSAGE.startswith("arrete")) and rdnb > 3:
logger.info(f"{user.name} - {message.guild.name} - A demandé d'arrêter")
reponses = [
"https://tenor.com/view/daddys-home2-daddys-home2gifs-stop-it-stop-that-i-mean-it-gif-9694318",
"https://tenor.com/view/stop-sign-when-you-catch-feelings-note-to-self-stop-now-gif-4850841",
"https://tenor.com/view/stop-it-get-some-help-gif-7929301",
]
await channel.send(random.choice(reponses))
if MESSAGE.startswith("exact") and rdnb > 2:
logger.info(f"{user.name} - {message.guild.name} - A trouvé ça exact")
reponses = [
"Je dirais même plus, exact.",
"Il est vrai",
"AH BON ??!",
"C'est cela",
"Plat-il ?",
"Jure ?",
]
await channel.send(random.choice(reponses))
if re.search(r'\bfeur\b', MESSAGE) and user.id == 302102401324679168:
await channel.send("@everyone ARRETEZ-TOUT, IL A DIT ***FEUR*** !!!")
if MESSAGE == "<3":
logger.info(f"{user.name} - {message.guild.name} - A envoyé de l'amour")
reponses = [
"Nique ta tante (pardon)",
"<3",
"luv luv",
"moi aussi je t'aime ❤",
]
await channel.send(random.choice(reponses))
if MESSAGE.strip(".;,?! \"')") in ["toi-même", "toi-meme", "toi même", "toi meme"]:
logger.info(f"{user.name} - {message.guild.name} - A sorti sa meilleure répartie")
reponses = [
"Je ne vous permet pas",
"Miroir magique",
"C'est celui qui dit qui l'est",
]
await channel.send(random.choice(reponses))
if "<@747066145550368789>" in message.content:
logger.info(f"{user.name} - {message.guild.name} - A parlé du grand bot")
reponses = [
"bae",
"Ah oui, cette sous-race de <@!747066145550368789>",
"il a moins de bits que moi",
"son pere est un con",
"ca se dit grand mais tout le monde sait que....",
]
await channel.send(random.choice(reponses))
if "❤" in MESSAGE:
logger.info(f"{user.name} - {message.guild.name} - A envoyé du love")
await message.add_reaction("❤")
if "🧂" in MESSAGE:
if rdnb > 3:
reponses_sel = [
"T'es une personne salée toi, nan ?",
"Au moins avec toi on tombera pas à court de sel...",
"Tu viens de la mer morte pour être aussi salé ?",
"Tiens, prends un peu d'eau avec tout ce sel.",
"Tu fais partie de l'îlot du sel ?",
"C'est pas bon pour la tension tout ce sel mon p'tit pote.",
"T'es saunier ?"
]
await channel.send(random.choice(reponses_sel))
logger.info(f"{user.name} - {message.guild.name} - A demandé à être salé")
else:
await message.add_reaction("🧂")
logger.info(f"{user.name} - {message.guild.name} - A reçu du sel")
if (MESSAGE.strip(".;,?! \"')") in ["hein", "1"]) and rdnb > 3:
logger.info(f"{user.name} - {message.guild.name} - A commencé par 1")
reponses = ["deux", "2", "deux ?", "2 😏"]
await channel.send(random.choice(reponses))
# waits for a message validating further instructions
def check_count(m):
logger.info(m.content)
return (("3" in m.content or "trois" in m.content)
and m.channel == message.channel
and not m.content.startswith("http"))
try:
await bot.wait_for("message", timeout=60.0, check=check_count)
except asyncio.TimeoutError:
await message.add_reaction("☹")
logger.info(f"{user.name} - {message.guild.name} - A pas su compter")
else:
logger.info(f"{user.name} - {message.guild.name} - A su compter")
reponses = [
"BRAVO TU SAIS COMPTER !",
"SOLEIL !",
"4, 5, 6, 7.... oh et puis merde",
"allez ta gueule.",
"stop.",
]
await channel.send(random.choice(reponses))
if MESSAGE == "a" and rdnb > 2:
logger.info(f"{user.name} - {message.guild.name} - A commencer par a")
def check_alphabet(m):
return m.content.lower(
) == "b" and m.channel == message.channel
try:
await bot.wait_for("message", timeout=60.0, check=check_alphabet)
except asyncio.TimeoutError:
await message.add_reaction("☹")
logger.info(f"{user.name} - {message.guild.name} - A pas continué par b")
else:
logger.info(f"{user.name} - {message.guild.name} - A connait son alphabet")
await channel.send("A B C GNEU GNEU MARRANT TROU DU CUL !!!")
if MESSAGE == "ah" and rdnb > 3:
if rdnb >= 4:
logger.info(f"{user.name} - {message.guild.name} - S'est fait Oh/Bh")
reponses = ["Oh", "Bh"]
await channel.send(random.choice(reponses))
else:
logger.info(f"{user.name} - {message.guild.name} - S'est fait répondre avec le dico (ah)")
await channel.send(finndAndReplace("a", dicoLines))
if MESSAGE == "oh" and rdnb >= 2:
logger.info(f"{user.name} - {message.guild.name} - ")
if rdnb >= 4:
logger.info(f"{user.name} - {message.guild.name} - S'est fait répondre (oh)")
reponses = [
"Quoi ?",
"p",
"ah",
":o",
"https://thumbs.gfycat.com/AptGrouchyAmericanquarterhorse-size_restricted.gif",
]
await channel.send(random.choice(reponses))
else:
logger.info(f"{user.name} - {message.guild.name} - S'est fait répondre par le dico (oh)")
await channel.send(finndAndReplace("o", dicoLines))
if MESSAGE == "eh" and rdnb >= 2:
if rdnb >= 4:
logger.info(f"{user.name} - {message.guild.name} - S'est fait répondre (eh)")
reponses = ["hehehehehe", "oh", "Du calme."]
await channel.send(random.choice(reponses))
else:
logger.info(f"{user.name} - {message.guild.name} - S'est fait répondre par le dico (eh)")
await channel.send(finndAndReplace("é", dicoLines))
if MESSAGE.startswith("merci"):
logger.info(f"{user.name} - {message.guild.name} - A dit merci")
if rdnb >= 3:
reponses = [
"De rien hehe",
"C'est normal t'inquiète",
"Je veux le cul d'la crémière avec.",
"non.",
"Excuse toi non ?",
"Au plaisir",
]
await channel.send(random.choice(reponses))
else:
await message.add_reaction("🥰")
if MESSAGE == "skusku" or MESSAGE == "sku sku":
logger.info(f"{user.name} - {message.guild.name} - A demandé qui jouait")
await channel.send("KICÉKIJOUE ????")
if ("😢" in MESSAGE or "😭" in MESSAGE) and rdnb >= 3:
logger.info(f"{user.name} - {message.guild.name} - A chialé")
reponses = [
"cheh",
"dur dur",
"dommage mon p'tit pote",
"balec",
"tant pis",
]
await channel.send(random.choice(reponses))