-
Notifications
You must be signed in to change notification settings - Fork 0
/
client.py
175 lines (122 loc) · 5.13 KB
/
client.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
import tkinter as tk
import os
import threading
import tkinter
from tkinter.scrolledtext import ScrolledText
from tkinter import BOTH, TOP, X, Y, simpledialog
from tkinter import ttk
import datetime as dt
try:
import socket
except:
os.system("pip install sockets")
import socket
HOST = '192.168.0.108'
PORT = 9999
msg_time = dt.datetime.now()
main_time = msg_time.strftime("%I:%M %p")
#the main class for running the client
class Client():
def __init__(self, host, port):
self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.client.connect((host, port))
print("Connected!")
nick_window = tk.Tk()
nick_window.withdraw()
self.nickname = simpledialog.askstring( "Nickname", "Enter your name...", parent=nick_window)
self.isGuiDone = False
self.isRunning = True
self.gui_thread = threading.Thread(target = self.gui_loop)
self.recieve_thread = threading.Thread(target = self.recieve_loop)
self.gui_thread.start()
self.recieve_thread.start()
def gui_loop(self):
#root configurations
self.main_window = tk.Tk()
self.main_window.configure(bg="#0a121b")
self.main_window.geometry("300x450")
self.main_window.title('TCP Chat')
self.main_window.iconbitmap('E:\Python Files\TCP Chat Room\chat_icon.ico')
#root bindings
self.main_window.bind('<Control-z>', self.undo)
#tabbed widgets
self.main_tab_container = ttk.Notebook(self.main_window)
self.main_tab_container.pack(expand=True, fill=BOTH)
#tabbed frames
self.chat_frame = tk.Frame(self.main_tab_container, bg="#0f2138")
self.chat_frame.pack()
self.chat_frame.focus()
self.settings_frame = tk.Frame(self.main_tab_container, bg="#0f2138")
self.settings_frame.pack()
#adding all the frames in the notebook
self.main_tab_container.add(self.chat_frame, text="Chat")
self.main_tab_container.add(self.settings_frame, text="Options")
#save chat logs
self.chat_log_button = tk.Button(self.settings_frame, text="Save Chat Log", font=("Fixedsys", 12), bg='#0f2138', fg='white', relief='flat', borderwidth=0,command=self.save_log)
self.chat_log_button.pack(side=TOP)
#scrolled text widget for showing the messages
self.message_area = ScrolledText(self.chat_frame, bg="#0f2138", fg="white", height=1, font=("Fixedsys", 12))
self.message_area.pack(fill=Y, expand=True)
self.message_area.config(state='disabled')
#taking the message input from the client
self.message_input = tk.Text(self.chat_frame, fg="white", bg="#0f2138", height=2, font=("Fixedsys", 12), undo=True)
self.message_input.pack()
self.message_input.focus_set()
#send message button
self.send_button = tk.Button(self.chat_frame, text="Send", bg="#0f2138", fg="white", highlightthickness=2, command=self.write_loop, font=("Fixedsys", 12))
self.send_button.pack()
#bool to let the program know that it has done building the GUI and now start the connection process
self.isGuiDone = True
self.main_window.protocol("WM_DELETE_WINDOW", self.stop)
self.main_window.mainloop()
#write messages loop
def write_loop(self):
msg = self.message_input.get(1.0, tk.END).strip()
if msg == "":
pass
else:
msg_to_send = f"{self.nickname} : {msg}\n"
self.client.send(msg_to_send.encode('utf-8'))
self.message_input.delete(1.0, tk.END)
#function to perform when the program closes
def stop(self):
self.isRunning = False
self.main_window.destroy()
self.client.close()
exit(0)
#loop for recieving messages and printing them
def recieve_loop(self):
while self.isRunning:
try:
message = self.client.recv(1024).decode('ascii')
if message == "NICK":
self.client.send(self.nickname.encode('ascii'))
else:
if self.isGuiDone:
self.insert_message(f"[{main_time}] {message}")
except ConnectionAbortedError:
break
except:
print("An error encountered!")
self.client.close()
break
#inserting the recieved message in the message area
def insert_message(self, msg):
self.message_area['state'] = tk.NORMAL
self.message_area.insert(tk.END, msg)
self.message_area.yview(tk.END)
self.message_area['state'] = tk.DISABLED
#changing the themes
def save_log(self):
self.chat_data = self.message_area.get('1.0','end')
with open('chat_log.txt', 'w') as log:
log.write(self.chat_data)
log.close()
#undo function for message input
def undo(self, event):
try:
self.message_input.edit_undo()
except tkinter.TclError:
pass
#for some reason the redo command is not working xD
CLIENT = Client(HOST, PORT)