├── docs ├── LICENSE └── README.md ├── poetry.lock ├── pyproject.toml ├── requirements.txt ├── src ├── Client.py ├── Management.py ├── Server.py └── images │ ├── icon.ico │ ├── logo.png │ ├── server.ico │ └── server.png ├── tests └── __init__.py ├── version.txt └── view ├── dle.jpg └── dlp.jpg /docs/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Shervin Badanara 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | Logo 4 | 5 |

Chat App

6 | 7 | Operating System | Version | Download 8 | ------------- | ------------- | ------------- 9 | Windows 11 | Latest 2.1.4 | [64Bit](https://codeload.github.com/shervinbdndev/ChatApp/zip/refs/heads/64-bit) 10 | Windows 10 | Latest 2.1.4 | [64Bit](https://codeload.github.com/shervinbdndev/ChatApp/zip/refs/heads/64-bit) , [32Bit](https://codeload.github.com/shervinbdndev/ChatApp/zip/refs/heads/32-bit) 11 | 12 |
13 |


14 |

15 | A Windows Open Source Chat Application For Your Home Routers. 16 |

17 | 18 |


19 |
20 |

English Dark & Light Modes

21 | 22 |
23 |


24 |

Persian Dark & Light Modes

25 | 26 |
27 |
28 | 29 |



30 | 31 |

Precendences

32 | 33 | - [x] Able To Run Server 34 | - [x] Able To Chat With Everyone 35 | - [x] Able To Switch Between Languages (Persian & English) 36 | - [x] Theme Synchronization 37 | 38 |
39 |



40 |

Language and technologies used in This Project

41 | 42 | 43 | 44 | 45 | 46 |



47 |

WorkSpace

48 | 49 | 50 | 51 |
52 | 53 | 54 |



55 | 56 |

How To Run

57 | 58 | First of All Clone the project from here ``~ git clone https://github.com/shervinbdndev/ChatApp.git`` 59 | 60 |
61 | 62 | Then go To Project's Directory with ``~ cd ChatApp-master`` 63 | 64 |
65 | 66 | For Running in Python Console 👇 67 | 68 |
69 | 70 | Windows : `` py -m pip install -r requirements.txt `` & `` cd .\src\ `` 71 | 72 |
73 | 74 | First Run The Server 👇 75 | 76 |
77 | 78 | ```py 79 | ~ py Server.py 80 | ``` 81 |
82 | 83 | Then Client 👇 84 | 85 |
86 | 87 | ```py 88 | ~ py Client.py 89 | ``` -------------------------------------------------------------------------------- /poetry.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "atomicwrites" 3 | version = "1.4.0" 4 | description = "Atomic file writes." 5 | category = "dev" 6 | optional = false 7 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 8 | 9 | [[package]] 10 | name = "attrs" 11 | version = "21.4.0" 12 | description = "Classes Without Boilerplate" 13 | category = "dev" 14 | optional = false 15 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 16 | 17 | [package.extras] 18 | dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit", "cloudpickle"] 19 | docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"] 20 | tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "cloudpickle"] 21 | tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "cloudpickle"] 22 | 23 | [[package]] 24 | name = "certifi" 25 | version = "2022.6.15" 26 | description = "Python package for providing Mozilla's CA Bundle." 27 | category = "main" 28 | optional = false 29 | python-versions = ">=3.6" 30 | 31 | [[package]] 32 | name = "charset-normalizer" 33 | version = "2.0.12" 34 | description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." 35 | category = "main" 36 | optional = false 37 | python-versions = ">=3.5.0" 38 | 39 | [package.extras] 40 | unicode_backport = ["unicodedata2"] 41 | 42 | [[package]] 43 | name = "colorama" 44 | version = "0.4.5" 45 | description = "Cross-platform colored terminal text." 46 | category = "dev" 47 | optional = false 48 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 49 | 50 | [[package]] 51 | name = "idna" 52 | version = "3.3" 53 | description = "Internationalized Domain Names in Applications (IDNA)" 54 | category = "main" 55 | optional = false 56 | python-versions = ">=3.5" 57 | 58 | [[package]] 59 | name = "more-itertools" 60 | version = "8.13.0" 61 | description = "More routines for operating on iterables, beyond itertools" 62 | category = "dev" 63 | optional = false 64 | python-versions = ">=3.5" 65 | 66 | [[package]] 67 | name = "packaging" 68 | version = "21.3" 69 | description = "Core utilities for Python packages" 70 | category = "dev" 71 | optional = false 72 | python-versions = ">=3.6" 73 | 74 | [package.dependencies] 75 | pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" 76 | 77 | [[package]] 78 | name = "pluggy" 79 | version = "0.13.1" 80 | description = "plugin and hook calling mechanisms for python" 81 | category = "dev" 82 | optional = false 83 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 84 | 85 | [package.extras] 86 | dev = ["pre-commit", "tox"] 87 | 88 | [[package]] 89 | name = "py" 90 | version = "1.11.0" 91 | description = "library with cross-python path, ini-parsing, io, code, log facilities" 92 | category = "dev" 93 | optional = false 94 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 95 | 96 | [[package]] 97 | name = "pyparsing" 98 | version = "3.0.9" 99 | description = "pyparsing module - Classes and methods to define and execute parsing grammars" 100 | category = "dev" 101 | optional = false 102 | python-versions = ">=3.6.8" 103 | 104 | [package.extras] 105 | diagrams = ["railroad-diagrams", "jinja2"] 106 | 107 | [[package]] 108 | name = "pytest" 109 | version = "5.4.3" 110 | description = "pytest: simple powerful testing with Python" 111 | category = "dev" 112 | optional = false 113 | python-versions = ">=3.5" 114 | 115 | [package.dependencies] 116 | atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} 117 | attrs = ">=17.4.0" 118 | colorama = {version = "*", markers = "sys_platform == \"win32\""} 119 | more-itertools = ">=4.0.0" 120 | packaging = "*" 121 | pluggy = ">=0.12,<1.0" 122 | py = ">=1.5.0" 123 | wcwidth = "*" 124 | 125 | [package.extras] 126 | checkqa-mypy = ["mypy (==v0.761)"] 127 | testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] 128 | 129 | [[package]] 130 | name = "requests" 131 | version = "2.28.0" 132 | description = "Python HTTP for Humans." 133 | category = "main" 134 | optional = false 135 | python-versions = ">=3.7, <4" 136 | 137 | [package.dependencies] 138 | certifi = ">=2017.4.17" 139 | charset-normalizer = ">=2.0.0,<2.1.0" 140 | idna = ">=2.5,<4" 141 | urllib3 = ">=1.21.1,<1.27" 142 | 143 | [package.extras] 144 | socks = ["PySocks (>=1.5.6,!=1.5.7)"] 145 | use_chardet_on_py3 = ["chardet (>=3.0.2,<5)"] 146 | 147 | [[package]] 148 | name = "urllib3" 149 | version = "1.26.9" 150 | description = "HTTP library with thread-safe connection pooling, file post, and more." 151 | category = "main" 152 | optional = false 153 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" 154 | 155 | [package.extras] 156 | brotli = ["brotlicffi (>=0.8.0)", "brotli (>=1.0.9)", "brotlipy (>=0.6.0)"] 157 | secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] 158 | socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] 159 | 160 | [[package]] 161 | name = "wcwidth" 162 | version = "0.2.5" 163 | description = "Measures the displayed width of unicode strings in a terminal" 164 | category = "dev" 165 | optional = false 166 | python-versions = "*" 167 | 168 | [metadata] 169 | lock-version = "1.1" 170 | python-versions = "^3.9" 171 | content-hash = "0785b2c54043aaa53d7d2d9b1b7ecdd29dd2d8608eaf8ddf64395de36e60a8aa" 172 | 173 | [metadata.files] 174 | atomicwrites = [ 175 | {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, 176 | {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, 177 | ] 178 | attrs = [ 179 | {file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"}, 180 | {file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"}, 181 | ] 182 | certifi = [ 183 | {file = "certifi-2022.6.15-py3-none-any.whl", hash = "sha256:fe86415d55e84719d75f8b69414f6438ac3547d2078ab91b67e779ef69378412"}, 184 | {file = "certifi-2022.6.15.tar.gz", hash = "sha256:84c85a9078b11105f04f3036a9482ae10e4621616db313fe045dd24743a0820d"}, 185 | ] 186 | charset-normalizer = [ 187 | {file = "charset-normalizer-2.0.12.tar.gz", hash = "sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597"}, 188 | {file = "charset_normalizer-2.0.12-py3-none-any.whl", hash = "sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df"}, 189 | ] 190 | colorama = [ 191 | {file = "colorama-0.4.5-py2.py3-none-any.whl", hash = "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da"}, 192 | {file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"}, 193 | ] 194 | idna = [ 195 | {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, 196 | {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, 197 | ] 198 | more-itertools = [ 199 | {file = "more-itertools-8.13.0.tar.gz", hash = "sha256:a42901a0a5b169d925f6f217cd5a190e32ef54360905b9c39ee7db5313bfec0f"}, 200 | {file = "more_itertools-8.13.0-py3-none-any.whl", hash = "sha256:c5122bffc5f104d37c1626b8615b511f3427aa5389b94d61e5ef8236bfbc3ddb"}, 201 | ] 202 | packaging = [ 203 | {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, 204 | {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, 205 | ] 206 | pluggy = [ 207 | {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"}, 208 | {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"}, 209 | ] 210 | py = [ 211 | {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, 212 | {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, 213 | ] 214 | pyparsing = [ 215 | {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"}, 216 | {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"}, 217 | ] 218 | pytest = [ 219 | {file = "pytest-5.4.3-py3-none-any.whl", hash = "sha256:5c0db86b698e8f170ba4582a492248919255fcd4c79b1ee64ace34301fb589a1"}, 220 | {file = "pytest-5.4.3.tar.gz", hash = "sha256:7979331bfcba207414f5e1263b5a0f8f521d0f457318836a7355531ed1a4c7d8"}, 221 | ] 222 | requests = [ 223 | {file = "requests-2.28.0-py3-none-any.whl", hash = "sha256:bc7861137fbce630f17b03d3ad02ad0bf978c844f3536d0edda6499dafce2b6f"}, 224 | {file = "requests-2.28.0.tar.gz", hash = "sha256:d568723a7ebd25875d8d1eaf5dfa068cd2fc8194b2e483d7b1f7c81918dbec6b"}, 225 | ] 226 | urllib3 = [ 227 | {file = "urllib3-1.26.9-py2.py3-none-any.whl", hash = "sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14"}, 228 | {file = "urllib3-1.26.9.tar.gz", hash = "sha256:aabaf16477806a5e1dd19aa41f8c2b7950dd3c746362d7e3223dbe6de6ac448e"}, 229 | ] 230 | wcwidth = [ 231 | {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, 232 | {file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"}, 233 | ] 234 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "ChatApp" 3 | version = "2.1.4" 4 | description = "" 5 | authors = ["shervinbdndev "] 6 | 7 | [tool.poetry.dependencies] 8 | python = "^3.9" 9 | requests = "^2.28.0" 10 | 11 | [tool.poetry.dev-dependencies] 12 | pytest = "^5.2" 13 | 14 | [build-system] 15 | requires = ["poetry-core>=1.0.0"] 16 | build-backend = "poetry.core.masonry.api" 17 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | tk 2 | customtkinter 3 | sv_ttk 4 | sockets 5 | ntkutils -------------------------------------------------------------------------------- /src/Client.py: -------------------------------------------------------------------------------- 1 | try: 2 | import os 3 | import sv_ttk 4 | import socket 5 | import tkinter 6 | import ntkutils 7 | import threading 8 | import webbrowser 9 | import darkdetect 10 | from typing_extensions import Self 11 | from tkinter.ttk import (Notebook , Frame) 12 | from tkinter.__init__ import (Text , StringVar) 13 | from customtkinter.widgets.customtkinter_entry import CTkEntry 14 | from customtkinter.widgets.customtkinter_button import CTkButton 15 | 16 | from Management import Materials 17 | 18 | except ModuleNotFoundError.__doc__ as mnfe: 19 | raise AttributeError(args='Cannot Run') from None 20 | 21 | finally: 22 | ... 23 | 24 | 25 | 26 | 27 | 28 | class Client: 29 | def __init__(self : Self) -> None: 30 | super(Client , self).__init__() 31 | self.root = tkinter.Tk() 32 | self.root.title(string=f'Client : {socket.gethostbyname(socket.gethostname())}') 33 | self.root.geometry(newGeometry='500x700') 34 | self.root.resizable(width=False , height=False) 35 | self.root.iconbitmap(bitmap=os.path.join(os.path.abspath(path=os.path.dirname(p=__file__)) , r'images/icon.ico')) 36 | self.tabControl = Notebook(master=self.root) 37 | self.tabChat = Frame(master=self.tabControl) 38 | self.tabLang = Frame(master=self.tabControl) 39 | self.tabAbout = Frame(master=self.tabControl) 40 | self.tabControl.add(child=self.tabChat , text='Chat') 41 | self.tabControl.add(child=self.tabLang , text='Language') 42 | self.tabControl.add(child=self.tabAbout , text='About') 43 | self.tabControl.pack(expand=1 , fill=Materials.Alignments.both) 44 | self.enMessage = StringVar(master=self.tabChat) 45 | self.clientSocket = socket.socket(socket.AF_INET , socket.SOCK_STREAM) 46 | self.clientSocket.setsockopt(socket.SOL_SOCKET , socket.SO_REUSEADDR , 1) 47 | self.port: int = 8000 48 | self.hostIP: str = '127.0.0.1' 49 | self.clientSocket.connect((self.hostIP , self.port)) 50 | 51 | def setBySystemTheme() -> None: 52 | if (darkdetect.isLight()): 53 | sv_ttk.set_theme(theme=Materials.Themes.LIGHT) 54 | self.textChat.configure(foreground=Materials.Colors.black) 55 | self.btnSend.configure(bg_color=Materials.Colors.white) 56 | self.btnPA.configure(bg_color=Materials.Colors.white) 57 | self.btnEN.configure(bg_color=Materials.Colors.white) 58 | self.btnGithub.configure(bg_color=Materials.Colors.white) 59 | self.root.update_idletasks() 60 | if (darkdetect.isDark()): 61 | sv_ttk.set_theme(theme=Materials.Themes.DARK) 62 | ntkutils.dark_title_bar(window=self.root) 63 | self.textChat.configure(foreground=Materials.Colors.white) 64 | self.btnSend.configure(bg_color=Materials.Colors.dark) 65 | self.btnPA.configure(bg_color=Materials.Colors.dark) 66 | self.btnEN.configure(bg_color=Materials.Colors.dark) 67 | self.btnGithub.configure(bg_color=Materials.Colors.dark) 68 | self.root.update_idletasks() 69 | 70 | def changeAppLanguage(arg : str) -> None: 71 | if (arg == 'PA'): 72 | self.root.title(string=f'دستگاه : {socket.gethostbyname(socket.gethostname())}') 73 | self.tabControl.add(child=self.tabChat , text='چت') 74 | self.tabControl.add(child=self.tabLang , text='زبان') 75 | self.tabControl.add(child=self.tabAbout , text='درباره') 76 | self.btnSend.configure(text='ارسال') 77 | self.btnPA.configure(text='پارسی') 78 | self.btnEN.configure(text='انگلیسی') 79 | self.btnGithub.configure(text='گیتهاب') 80 | if (self.enMessage.get() == ''): 81 | pass 82 | else: 83 | self.enMessage.set(value='پیام خود را وارد کنید') 84 | elif (arg == 'EN'): 85 | self.root.title(string=f'Client : {socket.gethostbyname(socket.gethostname())}') 86 | self.tabControl.add(child=self.tabChat , text='Chat') 87 | self.tabControl.add(child=self.tabLang , text='Language') 88 | self.tabControl.add(child=self.tabAbout , text='About') 89 | self.btnSend.configure(text='Send') 90 | self.btnPA.configure(text='Persian') 91 | self.btnEN.configure(text='English') 92 | self.btnGithub.configure(text='Github') 93 | if (self.enMessage.get() == ''): 94 | pass 95 | else: 96 | self.enMessage.set(value='Type Your Message Here') 97 | 98 | def aboutMeClickEvent() -> None: 99 | webbrowser.open(url='https://github.com/shervinbdndev') 100 | 101 | def sendMessage() -> None: 102 | msg = self.enMessage.get() 103 | self.textChat.insert(index=tkinter.END , chars=f"\n You: {msg}") 104 | self.clientSocket.send(msg.encode(encoding='utf-8')) 105 | 106 | def receiveMessage() -> None: 107 | while True: 108 | serverMessage = self.clientSocket.recv(1024).decode(encoding='utf-8') 109 | self.textChat.insert(index=tkinter.END , chars=f"\n {serverMessage}") 110 | 111 | def startRecieveing() -> None: 112 | recv = threading.Thread(target=receiveMessage) 113 | recv.daemon = True 114 | recv.start() 115 | 116 | self.textChat = Text( 117 | master=self.tabChat , 118 | width=53 , 119 | height=31 , 120 | bd=1 , 121 | border=1 , 122 | borderwidth=1 , 123 | font=(Materials.Fonts.pop , 12 , Materials.FontWeight.bold) , 124 | relief=Materials.Reliefs.groove , 125 | highlightcolor=Materials.Colors.medPurple , 126 | highlightbackground=Materials.Colors.medPurple , 127 | highlightthickness=1 , 128 | ) 129 | 130 | self.textChat.place(relx=0.5 , rely=0.46 , anchor=Materials.Alignments.center) 131 | 132 | self.entryMessage = CTkEntry( 133 | master=self.tabChat , 134 | textvariable=self.enMessage , 135 | corner_radius=5 , 136 | width=363 , 137 | height=40 , 138 | text_color=Materials.Colors.medPurple , 139 | text_font=(Materials.FontWeight.bold) , 140 | cursor=Materials.Cursors.hand , 141 | justify=Materials.Alignments.left , 142 | border_color=Materials.Colors.medPurple , 143 | state=Materials.State.normal , 144 | ) 145 | 146 | self.enMessage.set(value='Type Your Message Here') 147 | 148 | self.entryMessage.place(relx=0.377 , rely=0.95452 , anchor=Materials.Alignments.center) 149 | 150 | self.btnSend = CTkButton( 151 | master=self.tabChat , 152 | text='Send' , 153 | corner_radius=5 , 154 | width=100 , 155 | height=40 , 156 | text_color=Materials.Colors.white , 157 | text_font=(Materials.FontWeight.bold) , 158 | fg_color=Materials.Colors.medPurple , 159 | cursor=Materials.Cursors.hand , 160 | state=Materials.State.normal , 161 | command=sendMessage, 162 | ) 163 | 164 | self.btnSend.place(relx=0.882 , rely=0.95452 , anchor=Materials.Alignments.center) 165 | 166 | self.btnPA = CTkButton( 167 | master=self.tabLang , 168 | text='Persian' , 169 | corner_radius=5 , 170 | width=200 , 171 | height=60 , 172 | text_color=Materials.Colors.white , 173 | text_font=(Materials.FontWeight.bold) , 174 | fg_color=Materials.Colors.medPurple , 175 | cursor=Materials.Cursors.hand , 176 | state=Materials.State.normal , 177 | command=lambda:changeAppLanguage(arg='PA'), 178 | ) 179 | 180 | self.btnPA.place(relx=0.25 , rely=0.5 , anchor=Materials.Alignments.center) 181 | 182 | self.btnEN = CTkButton( 183 | master=self.tabLang , 184 | text='English' , 185 | corner_radius=5 , 186 | width=200 , 187 | height=60 , 188 | text_color=Materials.Colors.white , 189 | text_font=(Materials.FontWeight.bold) , 190 | fg_color=Materials.Colors.medPurple , 191 | cursor=Materials.Cursors.hand , 192 | state=Materials.State.normal , 193 | command=lambda:changeAppLanguage(arg='EN'), 194 | ) 195 | 196 | self.btnEN.place(relx=0.75 , rely=0.5 , anchor=Materials.Alignments.center) 197 | 198 | self.btnGithub = CTkButton( 199 | master=self.tabAbout , 200 | text='Github' , 201 | corner_radius=5 , 202 | width=200 , 203 | height=60 , 204 | text_color=Materials.Colors.white , 205 | text_font=(Materials.FontWeight.bold) , 206 | fg_color=Materials.Colors.medPurple , 207 | cursor=Materials.Cursors.hand , 208 | state=Materials.State.normal , 209 | command=aboutMeClickEvent, 210 | ) 211 | 212 | self.btnGithub.place(relx=0.5 , rely=0.5 , anchor=Materials.Alignments.center) 213 | 214 | setBySystemTheme() 215 | startRecieveing() 216 | 217 | self.root.mainloop() 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | def main() -> None: 226 | Client() 227 | 228 | 229 | 230 | 231 | 232 | if (__name__ == '__main__' and __package__ is None): 233 | main() -------------------------------------------------------------------------------- /src/Management.py: -------------------------------------------------------------------------------- 1 | try: 2 | from tkinter.font import BOLD 3 | from dataclasses import dataclass 4 | from tkinter.constants import (CENTER , NORMAL , BOTH , GROOVE , LEFT) 5 | 6 | except ModuleNotFoundError.__doc__ as mnfe: 7 | raise AttributeError(args='Cannot Import Materials') from None 8 | 9 | finally: 10 | ... 11 | 12 | 13 | 14 | 15 | 16 | @dataclass 17 | class Materials: 18 | 19 | @dataclass 20 | class Fonts: 21 | pop: str = 'Poplar Std' 22 | 23 | @dataclass 24 | class State: 25 | normal: str = NORMAL 26 | 27 | @dataclass 28 | class Cursors: 29 | hand: str = 'hand2' 30 | 31 | @dataclass 32 | class FontWeight: 33 | bold: str = BOLD 34 | 35 | @dataclass 36 | class Reliefs: 37 | groove: str = GROOVE 38 | 39 | @dataclass 40 | class Themes: 41 | DARK: str = 'dark' 42 | LIGHT: str = 'light' 43 | 44 | @dataclass 45 | class Colors: 46 | dark: str = '#1C1C1C' 47 | white: str = '#ffffff' 48 | black: str = '#000000' 49 | medPurple: str = '#5964e5' 50 | 51 | @dataclass 52 | class Alignments: 53 | both: str = BOTH 54 | left: str = LEFT 55 | center: str = CENTER -------------------------------------------------------------------------------- /src/Server.py: -------------------------------------------------------------------------------- 1 | try: 2 | import socket as skt 3 | from socket import socket 4 | from threading import Thread 5 | from dataclasses import dataclass 6 | from typing_extensions import Self 7 | 8 | except ModuleNotFoundError.__doc__ as mnfe: 9 | raise AttributeError(args='Cannot Run Server') from None 10 | 11 | finally: 12 | ... 13 | 14 | 15 | 16 | 17 | @dataclass 18 | class Users: 19 | clients = set() 20 | 21 | 22 | 23 | 24 | 25 | def clientThread(clientSocket : socket , clientAddress) -> None: 26 | while True: 27 | msg = clientSocket.recv(1024).decode(encoding='utf-8') 28 | print(f'{clientAddress[0]} : {str(clientAddress[1])} says: {msg}') 29 | for client in Users.clients: 30 | if (client is not clientSocket): 31 | client.send((f'{clientAddress[0]} : {str(clientAddress[1])} says: {msg}').encode(encoding='utf-8')) 32 | if (not msg): 33 | Users.clients.remove(clientSocket) 34 | print((f'{clientAddress[0]} : {str(clientAddress[1])} says: {msg}').encode(encoding='utf-8')) 35 | break 36 | clientSocket.close() 37 | 38 | 39 | hostSocket = socket(skt.AF_INET , skt.SOCK_STREAM) 40 | hostSocket.setsockopt(skt.SOL_SOCKET , skt.SO_REUSEADDR , 1) 41 | 42 | 43 | hostSocket.bind(('127.0.0.1' , 8000)) 44 | hostSocket.listen(1) 45 | print('Waiting For Connection . . .') 46 | 47 | 48 | if (__name__ == '__main__' and __package__ is None): 49 | while True: 50 | clientSocket , clientAddress = hostSocket.accept() 51 | Users.clients.add(clientSocket) 52 | print(f"Connection Stablished With: {clientAddress[0]} : {clientAddress[1]}") 53 | th = Thread(target=clientThread , args=(clientSocket , clientAddress , )) 54 | th.start() -------------------------------------------------------------------------------- /src/images/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shervinbdndev/ChatApp/ceb95b74315ad021e01d48f9e25daa16af816df1/src/images/icon.ico -------------------------------------------------------------------------------- /src/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shervinbdndev/ChatApp/ceb95b74315ad021e01d48f9e25daa16af816df1/src/images/logo.png -------------------------------------------------------------------------------- /src/images/server.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shervinbdndev/ChatApp/ceb95b74315ad021e01d48f9e25daa16af816df1/src/images/server.ico -------------------------------------------------------------------------------- /src/images/server.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shervinbdndev/ChatApp/ceb95b74315ad021e01d48f9e25daa16af816df1/src/images/server.png -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shervinbdndev/ChatApp/ceb95b74315ad021e01d48f9e25daa16af816df1/tests/__init__.py -------------------------------------------------------------------------------- /version.txt: -------------------------------------------------------------------------------- 1 | 2.1.4 -------------------------------------------------------------------------------- /view/dle.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shervinbdndev/ChatApp/ceb95b74315ad021e01d48f9e25daa16af816df1/view/dle.jpg -------------------------------------------------------------------------------- /view/dlp.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shervinbdndev/ChatApp/ceb95b74315ad021e01d48f9e25daa16af816df1/view/dlp.jpg --------------------------------------------------------------------------------