LouieFord

Client side

Aug 11th, 2022
323
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 18.89 KB | None | 0 0
  1. import socket
  2. import tkinter as tk
  3. from PIL import Image, ImageTk
  4. from tkinter import ttk
  5. from tkinter import filedialog
  6. from tkinter import messagebox
  7. import pickle
  8. from datetime import datetime
  9. import os
  10. import threading
  11. import struct
  12.  
  13.  
  14. try:
  15. from ctypes import windll
  16. windll.shcore.SetProcessDpiAwareness(1)
  17. except:
  18. pass
  19.  
  20.  
  21. class FirstScreen(tk.Tk):
  22. def __init__(self):
  23. super().__init__()
  24.  
  25. screen_width, screen_height = self.winfo_screenwidth(), self.winfo_screenheight()
  26.  
  27. self.x_co = int((screen_width / 2) - (550 / 2))
  28. self.y_co = int((screen_height / 2) - (400 / 2)) - 80
  29. self.geometry(f"550x400+{self.x_co}+{self.y_co}")
  30. self.title("Chatroom Login")
  31.  
  32. self.user = None
  33. self.image_extension = None
  34. self.image_path = None
  35.  
  36. self.first_frame = tk.Frame(self, bg="sky blue")
  37. self.first_frame.pack(fill="both", expand=True)
  38.  
  39.  
  40.  
  41. background = Image.open("images/login_bg_ca.jpg")
  42. background = background.resize((550, 400), Image.ANTIALIAS)
  43. background = ImageTk.PhotoImage(background)
  44.  
  45. upload_image = Image.open('images/upload_ca.png')
  46. upload_image = upload_image.resize((25, 25), Image.ANTIALIAS)
  47. upload_image = ImageTk.PhotoImage(upload_image)
  48.  
  49. self.user_image = 'images/user.png'
  50.  
  51. tk.Label(self.first_frame, image=background).place(x=0, y=0)
  52.  
  53. head = tk.Label(self.first_frame, text="Sign In", font="lucida 17 bold", bg="grey")
  54. head.place(relwidth=1, y=24)
  55.  
  56. self.profile_label = tk.Label(self.first_frame, bg="grey")
  57. self.profile_label.place(x=350, y=75, width=150, height=140)
  58.  
  59. upload_button = tk.Button(self.first_frame, image=upload_image, compound="left", text="Upload Image",
  60. cursor="hand2", font="lucida 12 bold", padx=2, command=self.add_photo)
  61. upload_button.place(x=345, y=220)
  62.  
  63. self.username = tk.Label(self.first_frame, text="Username", font="lucida 12 bold", bg="grey")
  64. self.username.place(x=80, y=150)
  65.  
  66. self.username_entry = tk.Entry(self.first_frame, font="lucida 12 bold", width=10,
  67. highlightcolor="blue", highlightthickness=1)
  68. self.username_entry.place(x=195, y=150)
  69.  
  70. self.password = tk.Label(self.first_frame, text="Password", font="lucida 12 bold", bg="grey")
  71. self.password.place(x=80, y=200)
  72.  
  73. self.password_entry = tk.Entry(self.first_frame, font="lucida 12 bold", width=10,
  74. highlightcolor="blue", highlightthickness=1)
  75. self.password_entry.place(x=195, y=200)
  76.  
  77. self.username_entry.focus_set()
  78.  
  79. submit_button = tk.Button(self.first_frame, text="Connect", font="lucida 12 bold", padx=30, cursor="hand2",
  80. command=self.process_data, bg="#16cade", relief="solid", bd=2)
  81.  
  82. submit_button.place(x=350, y=275)
  83.  
  84. register_button = tk.Button(self.first_frame, text="Register an Account", font="lucida 12 bold", padx=30, cursor="hand2",
  85. command=self.process_data, bg="#16cade", relief="solid", bd=2)
  86.  
  87. register_button.place(x=50, y=275)
  88.  
  89. self.mainloop()
  90.  
  91. def add_photo(self):
  92. self.image_path = filedialog.askopenfilename()
  93. image_name = os.path.basename(self.image_path)
  94. self.image_extension = image_name[image_name.rfind('.')+1:]
  95.  
  96. if self.image_path:
  97. user_image = Image.open(self.image_path)
  98. user_image = user_image.resize((150, 140), Image.ANTIALIAS)
  99. user_image.save('resized'+image_name)
  100. user_image.close()
  101.  
  102. self.image_path = 'resized'+image_name
  103. user_image = Image.open(self.image_path)
  104.  
  105. user_image = ImageTk.PhotoImage(user_image)
  106. self.profile_label.image = user_image
  107. self.profile_label.config(image=user_image)
  108.  
  109.  
  110. def process_data(self):
  111. if self.username_entry.get():
  112. self.profile_label.config(image="")
  113.  
  114. if len((self.username_entry.get()).strip()) > 6:
  115. self.user = self.username_entry.get()[:6]+"."
  116. else:
  117. self.user = self.username_entry.get()
  118.  
  119. client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  120. try:
  121. client_socket.connect(("localhost", 12345))
  122. status = client_socket.recv(1024).decode()
  123. if status == 'not_allowed':
  124. client_socket.close()
  125. messagebox.showinfo(title="Can't connect !", message='Sorry, server is completely occupied.'
  126. 'Try again later')
  127. return
  128.  
  129. except ConnectionRefusedError:
  130. messagebox.showinfo(title="Can't connect !", message="Server is offline , try again later.")
  131. print("Server is offline , try again later.")
  132. return
  133.  
  134. client_socket.send(self.user.encode('utf-8'))
  135.  
  136. if not self.image_path:
  137. self.image_path = self.user_image
  138. with open(self.image_path, 'rb') as image_data:
  139. image_bytes = image_data.read()
  140.  
  141. image_len = len(image_bytes)
  142. image_len_bytes = struct.pack('i', image_len)
  143. client_socket.send(image_len_bytes)
  144.  
  145. if client_socket.recv(1024).decode() == 'received':
  146. client_socket.send(str(self.image_extension).strip().encode())
  147.  
  148. client_socket.send(image_bytes)
  149.  
  150. clients_data_size_bytes = client_socket.recv(1024)
  151. clients_data_size_int = struct.unpack('i', clients_data_size_bytes)[0]
  152. b = b''
  153. while True:
  154. clients_data_bytes = client_socket.recv(1024)
  155. b += clients_data_bytes
  156. if len(b) == clients_data_size_int:
  157. break
  158.  
  159. clients_connected = pickle.loads(b)
  160.  
  161. client_socket.send('image_received'.encode())
  162.  
  163. user_id = struct.unpack('i', client_socket.recv(1024))[0]
  164. print(f"{self.user} is user no. {user_id}")
  165. ChatScreen(self, self.first_frame, client_socket, clients_connected, user_id)
  166.  
  167.  
  168. class ChatScreen(tk.Canvas):
  169. def __init__(self, parent, first_frame, client_socket, clients_connected, user_id):
  170. super().__init__(parent, bg="#2b2b2b")
  171.  
  172. self.window = 'ChatScreen'
  173.  
  174. self.first_frame = first_frame
  175. self.first_frame.pack_forget()
  176.  
  177. self.parent = parent
  178. self.parent.bind('<Return>', lambda e: self.sent_message_format(e))
  179.  
  180. self.all_user_image = {}
  181.  
  182. self.user_id = user_id
  183.  
  184.  
  185. self.clients_connected = clients_connected
  186.  
  187. # self.parent.protocol("WM_DELETE_WINDOW", lambda: self.on_closing(self.first_frame))
  188. self.parent.protocol("WM_DELETE_WINDOW", self.on_closing)
  189.  
  190. self.client_socket = client_socket
  191. screen_width, screen_height = self.winfo_screenwidth(), self.winfo_screenheight()
  192.  
  193. x_co = int((screen_width / 2) - (680 / 2))
  194. y_co = int((screen_height / 2) - (750 / 2)) - 80
  195. self.parent.geometry(f"680x750+{x_co}+{y_co}")
  196.  
  197. user_image = Image.open(self.parent.image_path)
  198. user_image = user_image.resize((40, 40), Image.ANTIALIAS)
  199. self.user_image = ImageTk.PhotoImage(user_image)
  200.  
  201. # global background
  202. # background = Image.open("images/chat_bg_ca.jpg")
  203. # background = background.resize((1600, 1500), Image.ANTIALIAS)
  204. # background = ImageTk.PhotoImage(background)
  205.  
  206. global group_photo
  207. group_photo = Image.open('images/group_ca.png')
  208. group_photo = group_photo.resize((60, 60), Image.ANTIALIAS)
  209. group_photo = ImageTk.PhotoImage(group_photo)
  210.  
  211. self.y = 140
  212. self.clients_online_labels = {}
  213.  
  214. # self.create_image(0, 0, image=background)
  215.  
  216. self.create_text(545, 120, text="Online", font="lucida 12 bold", fill="#40C961")
  217.  
  218. tk.Label(self, text=" ", font="lucida 15 bold", bg="#b5b3b3").place(x=4, y=29)
  219.  
  220. tk.Label(self, text="Group Chat", font="lucida 15 bold", padx=20, fg="green",
  221. bg="#b5b3b3", anchor="w", justify="left").place(x=88, y=29, relwidth=1)
  222.  
  223. self.create_image(60, 40, image=group_photo)
  224.  
  225. container = tk.Frame(self)
  226. # 595656
  227. # d9d5d4
  228. container.place(x=40, y=120, width=450, height=550)
  229. self.canvas = tk.Canvas(container, bg="#595656")
  230. self.scrollable_frame = tk.Frame(self.canvas, bg="#595656")
  231.  
  232. scrollable_window = self.canvas.create_window((0, 0), window=self.scrollable_frame, anchor="nw")
  233.  
  234. def configure_scroll_region(e):
  235. self.canvas.configure(scrollregion=self.canvas.bbox('all'))
  236.  
  237. def resize_frame(e):
  238. self.canvas.itemconfig(scrollable_window, width=e.width)
  239.  
  240. self.scrollable_frame.bind("<Configure>", configure_scroll_region)
  241.  
  242. scrollbar = ttk.Scrollbar(container, orient="vertical", command=self.canvas.yview)
  243. self.canvas.configure(yscrollcommand=scrollbar.set)
  244. self.yview_moveto(1.0)
  245.  
  246. scrollbar.pack(side="right", fill="y")
  247.  
  248. self.canvas.bind("<Configure>", resize_frame)
  249. self.canvas.pack(fill="both", expand=True)
  250.  
  251. send_button = tk.Button(self, text="Send", fg="#83eaf7", font="lucida 11 bold", bg="#7d7d7d", padx=10,
  252. relief="solid", bd=2, command=self.sent_message_format)
  253. send_button.place(x=400, y=680)
  254.  
  255. self.entry = tk.Text(self, font="lucida 10 bold", width=38, height=2,
  256. highlightcolor="blue", highlightthickness=1)
  257. self.entry.place(x=40, y=681)
  258.  
  259. self.entry.focus_set()
  260.  
  261.  
  262. m_frame = tk.Frame(self.scrollable_frame, bg="#d9d5d4")
  263.  
  264. t_label = tk.Label(m_frame, bg="#d9d5d4", text=datetime.now().strftime('%H:%M'), font="lucida 9 bold")
  265. t_label.pack()
  266.  
  267. m_label = tk.Label(m_frame, wraplength=250, text=f"Happy Chatting {self.parent.user}",
  268. font="lucida 10 bold", bg="orange")
  269. m_label.pack(fill="x")
  270.  
  271. m_frame.pack(pady=10, padx=10, fill="x", expand=True, anchor="e")
  272.  
  273. self.pack(fill="both", expand=True)
  274.  
  275. self.clients_online([])
  276.  
  277. t = threading.Thread(target=self.receive_data)
  278. t.setDaemon(True)
  279. t.start()
  280.  
  281. def receive_data(self):
  282. while True:
  283. try:
  284. data_type = self.client_socket.recv(1024).decode()
  285.  
  286. if data_type == 'notification':
  287. data_size = self.client_socket.recv(2048)
  288. data_size_int = struct.unpack('i', data_size)[0]
  289.  
  290. b = b''
  291. while True:
  292. data_bytes = self.client_socket.recv(1024)
  293. b += data_bytes
  294. if len(b) == data_size_int:
  295. break
  296. data = pickle.loads(b)
  297. self.notification_format(data)
  298.  
  299. else:
  300. data_bytes = self.client_socket.recv(1024)
  301. data = pickle.loads(data_bytes)
  302. self.received_message_format(data)
  303.  
  304. except ConnectionAbortedError:
  305. print("you disconnected ...")
  306. self.client_socket.close()
  307. break
  308. except ConnectionResetError:
  309. messagebox.showinfo(title='No Connection !', message="Server offline..try connecting again later")
  310. self.client_socket.close()
  311. self.first_screen()
  312. break
  313.  
  314. def on_closing(self):
  315. if self.window == 'ChatScreen':
  316. res = messagebox.askyesno(title='Warning !',message="Do you really want to disconnect ?")
  317. if res:
  318. import os
  319. os.remove(self.all_user_image[self.user_id])
  320. self.client_socket.close()
  321. self.first_screen()
  322. else:
  323. self.parent.destroy()
  324.  
  325. def received_message_format(self, data):
  326.  
  327. message = data['message']
  328. from_ = data['from']
  329.  
  330. sender_image = self.clients_connected[from_][1]
  331. sender_image_extension = self.clients_connected[from_][2]
  332.  
  333. # if not os.path.exists(f"{from_}.{sender_image_extension}"):
  334. with open(f"{from_}.{sender_image_extension}", 'wb') as f:
  335. f.write(sender_image)
  336.  
  337. im = Image.open(f"{from_}.{sender_image_extension}")
  338. im = im.resize((40, 40), Image.ANTIALIAS)
  339. im = ImageTk.PhotoImage(im)
  340.  
  341. m_frame = tk.Frame(self.scrollable_frame, bg="#595656")
  342.  
  343. m_frame.columnconfigure(1, weight=1)
  344.  
  345. t_label = tk.Label(m_frame, bg="#595656",fg="white", text=datetime.now().strftime('%H:%M'), font="lucida 7 bold",
  346. justify="left", anchor="w")
  347. t_label.grid(row=0, column=1, padx=2, sticky="w")
  348.  
  349. m_label = tk.Label(m_frame, wraplength=250,fg="black", bg="#c5c7c9", text=message, font="lucida 9 bold", justify="left",
  350. anchor="w")
  351. m_label.grid(row=1, column=1, padx=2, pady=2, sticky="w")
  352.  
  353. i_label = tk.Label(m_frame, bg="#595656", image=im)
  354. i_label.image = im
  355. i_label.grid(row=0, column=0, rowspan=2)
  356.  
  357. m_frame.pack(pady=10, padx=10, fill="x", expand=True, anchor="e")
  358.  
  359. self.canvas.update_idletasks()
  360. self.canvas.yview_moveto(1.0)
  361.  
  362. def sent_message_format(self, event=None):
  363.  
  364. message = self.entry.get('1.0', 'end-1c')
  365.  
  366. if message:
  367. if event:
  368. message = message.strip()
  369. self.entry.delete("1.0", "end-1c")
  370.  
  371. from_ = self.user_id
  372.  
  373. data = {'from': from_, 'message': message}
  374. data_bytes = pickle.dumps(data)
  375.  
  376. self.client_socket.send(data_bytes)
  377.  
  378. m_frame = tk.Frame(self.scrollable_frame, bg="#595656")
  379.  
  380. m_frame.columnconfigure(0, weight=1)
  381.  
  382. t_label = tk.Label(m_frame, bg="#595656", fg="white", text=datetime.now().strftime('%H:%M'),
  383. font="lucida 7 bold", justify="right", anchor="e")
  384. t_label.grid(row=0, column=0, padx=2, sticky="e")
  385.  
  386. m_label = tk.Label(m_frame, wraplength=250, text=message, fg="black", bg="#40C961",
  387. font="lucida 9 bold", justify="left",
  388. anchor="e")
  389. m_label.grid(row=1, column=0, padx=2, pady=2, sticky="e")
  390.  
  391. i_label = tk.Label(m_frame, bg="#595656", image=self.user_image)
  392. i_label.image = self.user_image
  393. i_label.grid(row=0, column=1, rowspan=2, sticky="e")
  394.  
  395. m_frame.pack(pady=10, padx=10, fill="x", expand=True, anchor="e")
  396.  
  397. self.canvas.update_idletasks()
  398. self.canvas.yview_moveto(1.0)
  399.  
  400. def notification_format(self, data):
  401. if data['n_type'] == 'joined':
  402.  
  403. name = data['name']
  404. image = data['image_bytes']
  405. extension = data['extension']
  406. message = data['message']
  407. client_id = data['id']
  408. self.clients_connected[client_id] = (name, image, extension)
  409. self.clients_online([client_id, name, image, extension])
  410. # print(self.clients_connected)
  411.  
  412. elif data['n_type'] == 'left':
  413. client_id = data['id']
  414. message = data['message']
  415. self.remove_labels(client_id)
  416. del self.clients_connected[client_id]
  417.  
  418. m_frame = tk.Frame(self.scrollable_frame, bg="#595656")
  419.  
  420. t_label = tk.Label(m_frame, fg="white", bg="#595656", text=datetime.now().strftime('%H:%M'),
  421. font="lucida 9 bold")
  422. t_label.pack()
  423.  
  424. m_label = tk.Label(m_frame, wraplength=250, text=message, font="lucida 10 bold", justify="left", bg="sky blue")
  425. m_label.pack()
  426.  
  427. m_frame.pack(pady=10, padx=10, fill="x", expand=True, anchor="e")
  428.  
  429. self.canvas.yview_moveto(1.0)
  430.  
  431. def clients_online(self, new_added):
  432. if not new_added:
  433. pass
  434. for user_id in self.clients_connected:
  435. name = self.clients_connected[user_id][0]
  436. image_bytes = self.clients_connected[user_id][1]
  437. extension = self.clients_connected[user_id][2]
  438.  
  439. with open(f"{user_id}.{extension}", 'wb') as f:
  440. f.write(image_bytes)
  441.  
  442. self.all_user_image[user_id] = f"{user_id}.{extension}"
  443.  
  444. user = Image.open(f"{user_id}.{extension}")
  445. user = user.resize((45, 45), Image.ANTIALIAS)
  446. user = ImageTk.PhotoImage(user)
  447.  
  448. b = tk.Label(self, image=user, text=name, compound="left",fg="white", bg="#2b2b2b", font="lucida 10 bold", padx=15)
  449. b.image = user
  450. self.clients_online_labels[user_id] = (b, self.y)
  451.  
  452. b.place(x=500, y=self.y)
  453. self.y += 60
  454.  
  455.  
  456. else:
  457. user_id = new_added[0]
  458. name = new_added[1]
  459. image_bytes = new_added[2]
  460. extension = new_added[3]
  461.  
  462. with open(f"{user_id}.{extension}", 'wb') as f:
  463. f.write(image_bytes)
  464.  
  465. self.all_user_image[user_id] = f"{user_id}.{extension}"
  466.  
  467. user = Image.open(f"{user_id}.{extension}")
  468. user = user.resize((45, 45), Image.ANTIALIAS)
  469. user = ImageTk.PhotoImage(user)
  470.  
  471. b = tk.Label(self, image=user, text=name, compound="left", fg="white", bg="#2b2b2b",
  472. font="lucida 10 bold", padx=15)
  473. b.image = user
  474. self.clients_online_labels[user_id] = (b, self.y)
  475.  
  476. b.place(x=500, y=self.y)
  477. self.y += 60
  478.  
  479. def remove_labels(self, client_id):
  480. for user_id in self.clients_online_labels.copy():
  481. b = self.clients_online_labels[user_id][0]
  482. y_co = self.clients_online_labels[user_id][1]
  483. if user_id == client_id:
  484. print("yes")
  485. b.destroy()
  486. del self.clients_online_labels[client_id]
  487. import os
  488. # os.remove(self.all_user_image[user_id])
  489.  
  490. elif user_id > client_id:
  491. y_co -= 60
  492. b.place(x=510, y=y_co)
  493. self.clients_online_labels[user_id] = (b, y_co)
  494. self.y -= 60
  495.  
  496.  
  497. def first_screen(self):
  498. self.destroy()
  499. self.parent.geometry(f"550x400+{self.parent.x_co}+{self.parent.y_co}")
  500. self.parent.first_frame.pack(fill="both", expand=True)
  501. self.window = None
  502.  
  503.  
  504. FirstScreen()
Advertisement
Add Comment
Please, Sign In to add comment