-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.py
More file actions
280 lines (209 loc) · 8.87 KB
/
Copy pathserver.py
File metadata and controls
280 lines (209 loc) · 8.87 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
import socket
import threading
import json
import discord
from discord.ext import commands, tasks
import asyncio
import configparser
config = configparser.ConfigParser()
config.read('master_config.ini')
TOKEN = config['Discord']['TOKEN']
GUILD_ID = int(config['Discord']['GUILD_ID'])
CHANNEL_ID = int(config['Discord']['CHANNEL_ID'])
POOL_SIZE = int(config['Server']['POOL_SIZE'])
LISTEN_PORT = int(config['Server']['LISTEN_PORT'])
with open('code.json', 'r') as file:
code_data = json.load(file)
all_codes = code_data['codes']
code_pools = [all_codes[i:i + POOL_SIZE] for i in range(0, len(all_codes), POOL_SIZE)]
client_sockets = {}
pending_codes = {}
used_codes = {}
used_codes_lock = threading.Lock()
client_names = {}
intents = discord.Intents.default()
intents.typing = False
intents.presences = False
bot = commands.Bot(command_prefix='!', intents=intents)
@bot.event
async def on_ready():
print(f'Logged in as {bot.user.name} - {bot.user.id}')
global status_message_id
status_channel = bot.get_channel(CHANNEL_ID)
status_message = None
try:
status_message = await status_channel.fetch_message(status_message_id)
await status(None)
except discord.HTTPException as e:
print(f"An error occurred while fetching the status message: {e}")
async for message in status_channel.history(limit=None):
await message.delete()
if status_message:
status_message_id = status_message.id
global guild
guild = bot.get_guild(GUILD_ID)
status_message_id = None
@bot.command()
@commands.guild_only()
async def status(ctx):
online_clients = len(client_sockets)
total_used_codes = sum(len(codes) for codes in used_codes.values())
used_percentage = (total_used_codes / len(all_codes)) * 100
message = (
f"📊 **Status Report** 📊\n\n"
f" {':green_circle:' if online_clients > 0 else ':red_circle:'} Online Clients: {online_clients}\n"
f"':bar_chart:' Used Code Percentage: {used_percentage:.2f}%\n"
)
for client_id, used_code_count in used_codes.items():
client_name = client_names.get(client_id, 'unknown')
client_used_percentage = (len(used_code_count) / len(all_codes)) * 100
client_info = f"• {client_name}: Used {len(used_code_count)} codes ({client_used_percentage:.2f}%)"
message += f"\n{client_info}"
global status_message_id
if status_message_id:
status_message = await bot.get_channel(CHANNEL_ID).fetch_message(status_message_id)
await status_message.edit(content=message)
else:
status_message = await bot.get_channel(CHANNEL_ID).send(message)
status_message_id = status_message.id
async def send_initial_status():
await bot.wait_until_ready()
global status_message_id
status_channel = bot.get_channel(CHANNEL_ID)
async for message in status_channel.history(limit=None):
await message.delete()
message = await status_channel.send("Initializing...")
status_message_id = message.id
while True:
online_clients = len(client_sockets)
total_used_codes = sum(len(codes) for codes in used_codes.values())
used_percentage = (total_used_codes / len(all_codes)) * 100
content = (
f"📊 **Status Report** 📊\n\n"
f" {':green_circle:' if online_clients > 0 else ':red_circle:'} Online Clients: {online_clients}\n"
f"':bar_chart:' Used Code Percentage: {used_percentage:.2f}%\n"
)
for client_id, used_code_count in used_codes.items():
client_name = client_names.get(client_id, 'unknown')
client_used_percentage = (len(used_code_count) / len(all_codes)) * 100
client_info = f"• {client_name}: Used {len(used_code_count)} codes ({client_used_percentage:.2f}%)"
content += f"\n{client_info}"
try:
message = await status_channel.fetch_message(status_message_id)
await message.edit(content=content)
except discord.NotFound:
message = await status_channel.send(content)
status_message_id = message.id
await asyncio.sleep(15)
@tasks.loop(seconds=15)
async def update_status():
await bot.wait_until_ready()
await status(None)
global status_message_id
if status_message_id:
status_message = await bot.get_channel(CHANNEL_ID).fetch_message(status_message_id)
def process_request(client_socket, client_id, request_data):
global client_names
if request_data == 'get_codes':
send_codes(client_socket, client_id)
elif request_data.startswith('confirm_code:'):
confirm_code_used(client_id, request_data.split(':')[1])
elif request_data.startswith('set_name:'):
set_client_name(client_id, request_data.split(':')[1])
elif request_data == 'get_names':
send_client_names(client_socket)
def handle_client(client_socket, client_address):
print(f"Client trying to connect from {client_address[0]}:{client_address[1]}")
client_id = client_address[0]
client_sockets[client_id] = client_socket
global client_names
client_name = None
while True:
try:
request_data = client_socket.recv(1024)
if not request_data:
break
request_data = request_data.decode('utf-8')
if request_data.startswith('set_name:'):
client_name = request_data.split(':')[1] # Update client name when set_name request is received
print(f"Client {client_address[0]}:{client_address[1]} set name to '{client_name}'")
process_request(client_socket, client_id, request_data)
except socket.error:
break
if client_id in client_sockets:
del client_sockets[client_id]
if client_id in pending_codes:
with used_codes_lock:
code_pools.insert(0, pending_codes.pop(client_id))
if client_id in client_names:
del client_names[client_id]
print(f"Client {client_name} disconnected.")
redistribute_codes()
def send_codes(client_socket, client_id):
global code_pools
if code_pools:
codes = code_pools.pop(0)
pending_codes[client_id] = codes
client_socket.send(json.dumps({'codes': codes}).encode('utf-8'))
else:
client_socket.send(json.dumps({'error': 'No codes available'}).encode('utf-8'))
def confirm_code_used(client_id, code):
with used_codes_lock:
if client_id in pending_codes and code in pending_codes[client_id]:
pending_codes[client_id].remove(code)
used_codes.setdefault(client_id, []).append(code)
client_name = client_names.get(client_id, 'unknown')
print(f'Code {code} confirmed as used by client \'{client_name}\'.')
def set_client_name(client_id, name):
name = name.strip()
if name:
client_names[client_id] = name
def send_client_names(client_socket):
global client_names
client_socket.send(json.dumps({'names': client_names}).encode('utf-8'))
def redistribute_codes():
while code_pools and client_sockets:
codes = code_pools.pop(0)
client_id, client_socket = client_sockets.popitem()
pending_codes[client_id] = codes
client_name = client_names.get(client_id, 'unknown')
print(f'Redistributing codes to client \'{client_name}\'.')
client_socket.send(json.dumps({'codes': codes}).encode('utf-8'))
@bot.command()
@commands.guild_only()
async def restart(ctx):
global code_pools, pending_codes, used_codes
code_pools = [all_codes[i:i + POOL_SIZE] for i in range(0, len(all_codes), POOL_SIZE)]
pending_codes.clear()
used_codes.clear()
await ctx.send("Code pools have been reset.")
@bot.command()
@commands.guild_only()
async def set_starting_code(ctx, starting_code: str):
global code_pools
if starting_code in all_codes:
index = all_codes.index(starting_code)
code_pools = [all_codes[index:index + POOL_SIZE] for index in range(index, len(all_codes), POOL_SIZE)]
await ctx.send(f"Code pools starting from '{starting_code}'.")
else:
await ctx.send("Starting code not found in the code list.")
async def background_tasks():
update_status.start()
def bot_thread():
bot.run(TOKEN)
def main():
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('0.0.0.0', LISTEN_PORT))
server_socket.listen(5)
print(f'Master Server listening on port {LISTEN_PORT}')
while True:
client_socket, client_address = server_socket.accept()
client_thread = threading.Thread(target=handle_client, args=(client_socket, client_address))
client_thread.start()
if __name__ == '__main__':
bot_thread = threading.Thread(target=bot_thread)
bot_thread.start()
loop = asyncio.get_event_loop()
loop.create_task(send_initial_status())
loop.create_task(background_tasks())
main()