-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.py
131 lines (106 loc) · 4.13 KB
/
server.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
import socket
import threading
#connection
host = '127.0.0.1'
port = 55555
#start server
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((host, port)) #binds to our host by passing tuple containing both values
server.listen()
# clients
clients = []
nicknames = []
# Sending Messages To All Connected Clients
def broadcast(message):
for client in clients:
client.send(message)
def ban_user(name_to_ban):
if name_to_ban in nicknames:
name_index = nicknames.index(name_to_ban)
client_to_ban = clients[name_index]
clients.remove(client_to_ban)
client_to_ban.send('You were banned by an admin.'.encode('ascii'))
client_to_ban.close()
nicknames.remove(name_to_ban)
broadcast(f'{name_to_ban} was banned by an admin!'.encode('ascii'))
with open('bans.txt', 'a') as f:
f.write(f'{name_to_ban}\n')
def safely_remove_client(client):
try:
index = clients.index(client)
clients.remove(client)
nickname = nicknames.pop(index)
client.close()
broadcast(f'{nickname} left!'.encode('ascii'))
except ValueError:
print("Client already removed")
#handling client messages
def handle(client):
while True:
try:
message = client.recv(1024).decode('ascii')
if message.startswith('KICK'):
if nicknames[clients.index(client)] == 'admin':
name_to_kick = message[5:]
kick_user(name_to_kick)
else:
client.send('Command was refused!'.encode('ascii'))
elif message.startswith('BAN'):
if nicknames[clients.index(client)] == 'admin':
name_to_ban = message[4:]
ban_user(name_to_ban)
else:
client.send('Command was refused!'.encode('ascii'))
else:
broadcast(message.encode('ascii'))
except Exception as e:
print(f'Error handling message: {e}')
safely_remove_client(client)
break
# Receiving / Listening Function
def receive():
while True:
#accept connect
client, address = server.accept()
print("Connected with {}".format(str(address)))
#request
client.send("NICKNAME".encode('ascii'))
nickname = client.recv(1024).decode('ascii')
with open('bans.txt', 'r') as f:
bans = [line.strip() for line in f]
# bans = [line.strip() for line in f]
# if nickname in bans:
if nickname in bans:
client.send('BAN'.encode('ascii'))
client.close()
continue
#admin password check
if nickname == 'admin':
client.send('PASSWORD'.encode('ascii'))
password = client.recv(1024).decode('ascii')
#real world need to be hashed in DB
if password != 'atractivePW':
client.send('REFUSE'.encode('ascii'))
client.close()
continue #this thread to connect and we have other threads to connect
# if fail will skip look for another
#store
nicknames.append(nickname)
clients.append(client)
#print & broadcast
print(f'Nickname is {nickname}')
broadcast(f'{nickname} joined!'.encode('ascii'))
client.send('Connected to server!'.encode('ascii'))
#new THREAD for client
thread = threading.Thread(target=handle, args=(client,))
thread.start()
def kick_user(name):
if name in nicknames:
name_index = nicknames.index(name)
client_to_kick = clients[name_index]
clients.remove(client_to_kick)
client_to_kick.send('you were kicked by an admin'.encode('ascii'))
client_to_kick.close()
nicknames.remove(name)
broadcast(f'{name} was kicked by an admin!'.encode('ascii'))
receive()