Mariorower commited on
Commit
99fcc2f
·
verified ·
1 Parent(s): 4ec347e

Upload bot.py

Browse files
Files changed (1) hide show
  1. bot.py +241 -0
bot.py ADDED
@@ -0,0 +1,241 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import discord
2
+ from discord.ext import commands, tasks
3
+ from discord import app_commands
4
+ from datetime import datetime, timedelta
5
+ from zoneinfo import ZoneInfo
6
+ import json
7
+ import os
8
+
9
+ TOKEN = "MTQzNzQyMzM5Mzk5MjYwNTc5OQ.G7YuIP.W-tSbjR5iRgkvWYKwq1z2TKKoVmU6c2qCw4mB8"
10
+
11
+ CHANNEL_NAME = "︙🏖️︙urlopy"
12
+ BACKUP_CHANNEL = "︙📦︙backup-urlopy"
13
+
14
+ intents = discord.Intents.default()
15
+ intents.members = True
16
+ intents.voice_states = True
17
+
18
+ bot = commands.Bot(command_prefix="!", intents=intents)
19
+
20
+ active_leaves = {}
21
+ voice_time = {}
22
+ backup_message_id = None
23
+
24
+
25
+ # ================= BACKUP =================
26
+
27
+ async def save_backup():
28
+ global backup_message_id
29
+
30
+ for guild in bot.guilds:
31
+ channel = discord.utils.get(guild.text_channels, name=BACKUP_CHANNEL)
32
+ if not channel:
33
+ continue
34
+
35
+ data = {
36
+ str(user_id): {
37
+ "start": str(start),
38
+ "end": str(end),
39
+ "nick": nick
40
+ }
41
+ for user_id, (start, end, nick) in active_leaves.items()
42
+ }
43
+
44
+ content = json.dumps(data)
45
+
46
+ try:
47
+ if backup_message_id:
48
+ msg = await channel.fetch_message(backup_message_id)
49
+ await msg.edit(content=content)
50
+ return
51
+ except:
52
+ backup_message_id = None
53
+
54
+ async for msg in channel.history(limit=10):
55
+ backup_message_id = msg.id
56
+ await msg.edit(content=content)
57
+ return
58
+
59
+ msg = await channel.send(content)
60
+ backup_message_id = msg.id
61
+
62
+
63
+ async def load_backup():
64
+ global backup_message_id
65
+
66
+ for guild in bot.guilds:
67
+ channel = discord.utils.get(guild.text_channels, name=BACKUP_CHANNEL)
68
+ if not channel:
69
+ continue
70
+
71
+ async for msg in channel.history(limit=10):
72
+ try:
73
+ data = json.loads(msg.content)
74
+ backup_message_id = msg.id
75
+
76
+ for user_id, val in data.items():
77
+ active_leaves[int(user_id)] = (
78
+ datetime.strptime(val["start"], "%Y-%m-%d").date(),
79
+ datetime.strptime(val["end"], "%Y-%m-%d").date(),
80
+ val["nick"]
81
+ )
82
+ return
83
+ except:
84
+ continue
85
+
86
+
87
+ # ================= READY =================
88
+
89
+ @bot.event
90
+ async def on_ready():
91
+ await bot.tree.sync()
92
+ await load_backup()
93
+ leave_manager.start()
94
+ print(f"Zalogowano jako {bot.user}")
95
+
96
+
97
+ # ================= KOMENDA =================
98
+
99
+ @bot.tree.command(name="urlop")
100
+ async def urlop(interaction: discord.Interaction, od: str, do: str, powod: str):
101
+
102
+ await interaction.response.defer() # 🔥 FIX 404 INTERACTION
103
+
104
+ try:
105
+ now = datetime.now(ZoneInfo("Europe/Warsaw"))
106
+ today = now.date()
107
+ year = now.year
108
+
109
+ member = interaction.user
110
+
111
+ def reject(reason):
112
+ return (
113
+ f"❌ {member.mention} próbował wziąć urlop!\n\n"
114
+ f"Od: **{od}**\n"
115
+ f"Do: **{do}**\n"
116
+ f"Powód: {powod}\n\n"
117
+ f"🚫 Odrzucono: {reason}"
118
+ )
119
+
120
+ channel = discord.utils.get(interaction.guild.text_channels, name=CHANNEL_NAME)
121
+
122
+ if interaction.channel.name != CHANNEL_NAME:
123
+ return await interaction.followup.send("❌ Użyj komendy na kanale urlopy!")
124
+
125
+ # ⛔ TYLKO PO 22:00 BLOKADA (PRZED 12:00 JUŻ DZIAŁA)
126
+ if now.hour >= 22:
127
+ return await interaction.followup.send(reject("Urlopy zablokowane po 22:00"))
128
+
129
+ start = datetime.strptime(f"{od}.{year}", "%d.%m.%Y").date()
130
+ end_real = datetime.strptime(f"{do}.{year}", "%d.%m.%Y").date()
131
+
132
+ if start < today:
133
+ return await interaction.followup.send(reject("Nie możesz brać urlopu w przeszłości"))
134
+
135
+ if start > today + timedelta(days=7):
136
+ return await interaction.followup.send(reject("Max 7 dni do przodu"))
137
+
138
+ dni = (end_real - start).days + 1
139
+
140
+ if dni < 2:
141
+ return await interaction.followup.send(reject("Minimum 2 dni"))
142
+
143
+ if dni > 7:
144
+ return await interaction.followup.send(reject("Max 7 dni"))
145
+
146
+ if member.id in active_leaves and "[URLOP]" not in member.display_name:
147
+ del active_leaves[member.id]
148
+ await save_backup()
149
+
150
+ if "[URLOP]" in member.display_name or member.id in active_leaves:
151
+ return await interaction.followup.send(reject("Masz już aktywny urlop"))
152
+
153
+ remove_date = end_real + timedelta(days=1)
154
+ active_leaves[member.id] = (start, remove_date, False)
155
+
156
+ await save_backup()
157
+
158
+ await channel.send(
159
+ f"📅 {member.mention} zgłosił urlop!\n"
160
+ f"Od: **{od}**\n"
161
+ f"Do: **{do}**\n"
162
+ f"Dni: **{dni}**\n"
163
+ f"Powód: {powod}"
164
+ )
165
+
166
+ await interaction.followup.send("✅ Urlop zapisany!")
167
+
168
+ except Exception as e:
169
+ await interaction.followup.send(f"❌ Błąd dat! Użyj DD.MM")
170
+
171
+
172
+ # ================= SYSTEM =================
173
+
174
+ @tasks.loop(minutes=5)
175
+ async def leave_manager():
176
+ today = datetime.now(ZoneInfo("Europe/Warsaw")).date()
177
+
178
+ for user_id in list(active_leaves.keys()):
179
+ start, remove_date, nick_dany = active_leaves[user_id]
180
+
181
+ for guild in bot.guilds:
182
+ member = guild.get_member(user_id)
183
+ if not member:
184
+ continue
185
+
186
+ channel = discord.utils.get(guild.text_channels, name=CHANNEL_NAME)
187
+
188
+ if today >= start and not nick_dany:
189
+ try:
190
+ new_nick = f"{member.display_name} [URLOP]"
191
+ new_nick = new_nick[:32]
192
+
193
+ await member.edit(nick=new_nick)
194
+ await channel.send(f"🟢 {member.mention} rozpoczął urlop!")
195
+ except:
196
+ pass
197
+
198
+ active_leaves[user_id] = (start, remove_date, True)
199
+ await save_backup()
200
+
201
+ if today >= remove_date:
202
+ try:
203
+ await member.edit(nick=member.display_name.replace(" [URLOP]", ""))
204
+ await channel.send(f"🔴 {member.mention} zakończył urlop!")
205
+ except:
206
+ pass
207
+
208
+ del active_leaves[user_id]
209
+ await save_backup()
210
+
211
+
212
+ # ================= VOICE =================
213
+
214
+ @bot.event
215
+ async def on_voice_state_update(member, before, after):
216
+
217
+ if after.channel and member.id in active_leaves:
218
+ voice_time[member.id] = datetime.now(ZoneInfo("Europe/Warsaw"))
219
+
220
+ if before.channel and not after.channel:
221
+ if member.id in voice_time:
222
+ czas = datetime.now(ZoneInfo("Europe/Warsaw")) - voice_time[member.id]
223
+
224
+ if czas.total_seconds() >= 3600:
225
+ for guild in bot.guilds:
226
+ channel = discord.utils.get(guild.text_channels, name=CHANNEL_NAME)
227
+
228
+ try:
229
+ await member.edit(nick=member.display_name.replace(" [URLOP]", ""))
230
+ await channel.send(f"⚡ {member.mention} wrócił wcześniej z urlopu!")
231
+ except:
232
+ pass
233
+
234
+ if member.id in active_leaves:
235
+ del active_leaves[member.id]
236
+ await save_backup()
237
+
238
+ del voice_time[member.id]
239
+
240
+
241
+ bot.run(TOKEN)