lantalk 2.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
lantalk-2.0.0/LICENCE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ezra Destaw
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.
lantalk-2.0.0/PKG-INFO ADDED
@@ -0,0 +1,300 @@
1
+ Metadata-Version: 2.4
2
+ Name: lantalk
3
+ Version: 2.0.0
4
+ Summary: Terminal-based LAN chat — async, discoverable, secure
5
+ Author-email: Ezra Destaw <ezradestaw@email.com>
6
+ Project-URL: Homepage, https://github.com/Ezradestaw/lantalk
7
+ Project-URL: Repository, https://github.com/Ezradestaw/lantalk
8
+ Project-URL: Issues, https://github.com/Ezradestaw/lantalk/issues
9
+ Keywords: chat,lan,wifi,terminal,networking,broadcast,asyncio
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Environment :: Console
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Intended Audience :: End Users/Desktop
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3 :: Only
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Topic :: Communications :: Chat
22
+ Classifier: Topic :: Internet
23
+ Requires-Python: >=3.10
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENCE
26
+ Provides-Extra: dev
27
+ Requires-Dist: pytest>=8.0; extra == "dev"
28
+ Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
29
+ Dynamic: license-file
30
+
31
+ # LanTalk
32
+
33
+ > Terminal-based LAN chat — pure asyncio, auto-discoverable, zero runtime dependencies.
34
+
35
+ ```
36
+ _ _____ _ _
37
+ | | |_ _| | | |
38
+ | | __ _ _ __ | | __ _| | | __
39
+ | | / _` | '_ \ | |/ _` | | |/ /
40
+ | |___| (_| | | | || | (_| | | <
41
+ |______\__,_|_| |_\_/ \__,_|_|_|\_\
42
+ ```
43
+
44
+ [![PyPI version](https://img.shields.io/pypi/v/lantalk)](https://pypi.org/project/lantalk/)
45
+ [![Python](https://img.shields.io/pypi/pyversions/lantalk)](https://pypi.org/project/lantalk/)
46
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
47
+
48
+ ---
49
+
50
+ ## What is LanTalk?
51
+
52
+ LanTalk lets people on the **same Wi-Fi or LAN** chat instantly — no accounts, no internet, no servers in the cloud. One person runs `lantalk` and starts a server; everyone else runs `lantalk` and joins. That's it.
53
+
54
+ - Works on school networks, home networks, offices, hackathons
55
+ - Pure Python stdlib — nothing to `pip install` beyond the package itself
56
+ - Clients auto-discover the server via UDP broadcast (no IP typing required)
57
+
58
+ ---
59
+
60
+ ## Features
61
+
62
+ | | |
63
+ |---|---|
64
+ | 🔍 **Auto-discovery** | UDP beacon finds servers on your LAN automatically |
65
+ | 🔐 **Password auth** | Optional server password with SHA-256 hashing |
66
+ | 👤 **Username dedup** | Two people can't use the same name simultaneously |
67
+ | 💬 **Private messages** | `/pm <user> <message>` — end-to-end on the wire |
68
+ | 🛡 **Rate limiting** | Spammers get warned then kicked (10 msg / 5 s) |
69
+ | ⏱ **Idle timeouts** | Dead sockets cleaned up after 5 minutes of silence |
70
+ | 🚫 **Persistent bans** | Banned IPs survive server restarts via `bans.json` |
71
+ | 🔇 **Full validation** | Every message checked for type and field constraints |
72
+ | 📝 **Structured logging** | Console + `lantalk.log` file, levels DEBUG/INFO/WARNING |
73
+ | ⚡ **Pure asyncio** | Single event loop — no threads, no race conditions |
74
+
75
+ ---
76
+
77
+ ## Install
78
+
79
+ ```bash
80
+ pip install lantalk
81
+ ```
82
+
83
+ Python 3.10+ required. No third-party dependencies.
84
+
85
+ ### From source
86
+
87
+ ```bash
88
+ git clone https://github.com/yourusername/lantalk
89
+ cd lantalk
90
+ pip install -e ".[dev]"
91
+ ```
92
+
93
+ ---
94
+
95
+ ## Quick start
96
+
97
+ ### 1 — Start a server (one person does this)
98
+
99
+ ```
100
+ $ lantalk
101
+
102
+ [1] Start a Server
103
+ [2] Join as Client
104
+
105
+ Choose (1 or 2): 1
106
+ Port (default 5050):
107
+ Server display name: Alice
108
+ Set password (leave blank for none): secret
109
+
110
+ ══════════════════════════════════════════════════════
111
+ LanTalk Server v2.0.0 — Alice
112
+ Listening on 192.168.1.5:5050
113
+ Discovery beacon active (UDP 5051)
114
+ Password protection: ON
115
+ ══════════════════════════════════════════════════════
116
+ ```
117
+
118
+ ### 2 — Join as a client (everyone else)
119
+
120
+ ```
121
+ $ lantalk
122
+
123
+ [1] Start a Server
124
+ [2] Join as Client
125
+
126
+ Choose (1 or 2): 2
127
+ Scanning for LanTalk servers…
128
+ Found 1 server(s):
129
+
130
+ [1] 192.168.1.5:5050
131
+ [m] Enter manually
132
+
133
+ Choose server: 1
134
+ Display name: Bob
135
+ Password: secret
136
+
137
+ ══════════════════════════════════════════════════════
138
+ LanTalk Client v2.0.0 — Bob
139
+ Connected to 192.168.1.5:5050
140
+ Commands: /users /pm <user> <msg> /quit
141
+ ══════════════════════════════════════════════════════
142
+ [Bob | lantalk] > Hey everyone!
143
+ [14:22] Alice: Welcome Bob!
144
+ [Bob | lantalk] > /pm Alice just between us 👋
145
+ [Bob | lantalk] > /users
146
+ [14:23] *** Online: Alice, Bob, Carol ***
147
+ [Bob | lantalk] >
148
+ ```
149
+
150
+ ---
151
+
152
+ ## Commands
153
+
154
+ ### Client commands
155
+
156
+ | Command | Description |
157
+ |---------|-------------|
158
+ | `/users` | List all connected users |
159
+ | `/pm <user> <message>` | Send a private message |
160
+ | `/quit` | Disconnect and exit |
161
+
162
+ ### Server console commands
163
+
164
+ | Command | Description |
165
+ |---------|-------------|
166
+ | `/users` | List connected users |
167
+ | `/stats` | Show connection count and ban list size |
168
+ | `/kick <user>` | Disconnect a user |
169
+ | `/ban <user>` | Ban a user's IP (persisted to `bans.json`) |
170
+ | `/bans` | Show all banned IPs |
171
+ | `/unban <ip>` | Remove an IP from the ban list |
172
+ | `/help` | Show this list |
173
+ | `/quit` | Shut down the server |
174
+ | *(anything else)* | Broadcast as a server message to all clients |
175
+
176
+ ---
177
+
178
+ ## Architecture
179
+
180
+ ```
181
+ ┌──────────────────────────────────────────────────────────────┐
182
+ │ LAN (e.g. 192.168.1.0/24) │
183
+ │ │
184
+ │ ┌────────────────────────────────────┐ │
185
+ │ │ LanTalkServer (pure asyncio) │ │
186
+ │ │ │◄─── TCP :5050 ───┐ │
187
+ │ │ _discovery_beacon() ─────────────┼──── UDP bcast │ │
188
+ │ │ asyncio coroutine, no threads │ every 2 s │ │
189
+ │ │ │ │ │
190
+ │ │ per-client _RateLimiter │ │ │
191
+ │ │ _validate() on every message │ │ │
192
+ │ │ asyncio.wait_for() timeouts │ │ │
193
+ │ │ bans.json (persistent) │ │ │
194
+ │ │ lantalk.log (structured) │ │ │
195
+ │ └────────────────────────────────────┘ │ │
196
+ │ │ │
197
+ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┴─┐ │
198
+ │ │ Client A │ │ Client B │ │ Client C │ │
199
+ │ │ UDP discover │ │ UDP discover │ │ manual IP entry │ │
200
+ │ │ asyncio │ │ asyncio │ │ asyncio │ │
201
+ │ └──────────────┘ └──────────────┘ └────────────────────┘ │
202
+ └──────────────────────────────────────────────────────────────┘
203
+
204
+ Message flow (post-auth):
205
+ Client ──JSON──► Server ──broadcast JSON──► all other Clients
206
+ └──(PM)──────────► one Client
207
+ ```
208
+
209
+ ### Concurrency model
210
+
211
+ Everything runs in **one asyncio event loop** — no `threading.Thread`, no locks between threads, no shared mutable state across OS threads. The only `asyncio.Lock` is used to guard the `_clients` dict between concurrent coroutines.
212
+
213
+ ### JSON wire protocol
214
+
215
+ Every message is a single UTF-8 JSON line terminated with `\n`.
216
+
217
+ ```jsonc
218
+ // Server → Client: auth challenge
219
+ {"type": "auth_request", "ts": "14:22", "needs_password": true}
220
+
221
+ // Client → Server: credentials
222
+ {"username": "Bob", "password": "secret"}
223
+
224
+ // Server → Client: success / failure
225
+ {"type": "auth_ok", "ts": "…", "username": "Bob", "server_name": "Alice"}
226
+ {"type": "auth_fail", "ts": "…", "reason": "Username already taken."}
227
+
228
+ // Client → Server: chat message
229
+ {"type": "message", "text": "Hello!"}
230
+
231
+ // Server → all clients: broadcast
232
+ {"type": "message", "ts": "14:22", "user": "Bob", "text": "Hello!"}
233
+
234
+ // Server → one client: private message
235
+ {"type": "pm", "ts": "14:22", "from_user": "Alice", "text": "hey"}
236
+
237
+ // Server → clients: system event
238
+ {"type": "system", "ts": "14:22", "text": "Bob joined from 192.168.1.10."}
239
+ ```
240
+
241
+ ---
242
+
243
+ ## Security notes
244
+
245
+ - Passwords are **never stored or sent in plaintext**. The server stores a SHA-256 hash; clients send the raw password only during the auth handshake (upgrade to TLS in v3 is planned).
246
+ - Banned IPs are written to `bans.json` in the server's working directory and reloaded on every start.
247
+ - Rate limiting: each client is capped at **10 messages per 5 seconds**. Exceeding this sends a warning; repeat offences kick the user.
248
+ - Usernames are limited to 24 alphanumeric/underscore/hyphen characters.
249
+ - All incoming messages are schema-validated before processing; malformed JSON is silently dropped.
250
+
251
+ ---
252
+
253
+ ## Logging
254
+
255
+ LanTalk writes structured logs to both the terminal and `lantalk.log`:
256
+
257
+ ```
258
+ [14:22:01] INFO Server started on 192.168.1.5:5050
259
+ [14:22:15] INFO Bob joined from 192.168.1.10
260
+ [14:23:44] WARNING Carol hit rate limit
261
+ [14:25:01] INFO Kicked Dave
262
+ [14:25:03] INFO Banned Dave (192.168.1.22)
263
+ ```
264
+
265
+ Set `LANTALK_LOG_LEVEL=DEBUG` to see per-message traces.
266
+
267
+ ---
268
+
269
+ ## Running tests
270
+
271
+ ```bash
272
+ pip install -e ".[dev]"
273
+ pytest -v
274
+ ```
275
+
276
+ ---
277
+
278
+ ## Changelog
279
+
280
+ ```
281
+ 2.0.0 — pure asyncio (no threads), validation, rate limiting,
282
+ timeouts, persistent bans, structured logging, v2 prompt
283
+ 1.1.0 — asyncio rewrite, UDP discovery, JSON protocol, auth, commands, pytest
284
+ 1.0.0 — initial: threading, basic TCP, plain-text protocol
285
+ ```
286
+
287
+ ---
288
+
289
+ ## Roadmap
290
+
291
+ - [ ] TLS encryption (v3)
292
+ - [ ] File transfer (`/send file.pdf`)
293
+ - [ ] Web UI mode (`http://localhost:5050`)
294
+ - [ ] Plugin system (`@lantalk.plugin`)
295
+
296
+ ---
297
+
298
+ ## License
299
+
300
+ MIT © Ezra
@@ -0,0 +1,270 @@
1
+ # LanTalk
2
+
3
+ > Terminal-based LAN chat — pure asyncio, auto-discoverable, zero runtime dependencies.
4
+
5
+ ```
6
+ _ _____ _ _
7
+ | | |_ _| | | |
8
+ | | __ _ _ __ | | __ _| | | __
9
+ | | / _` | '_ \ | |/ _` | | |/ /
10
+ | |___| (_| | | | || | (_| | | <
11
+ |______\__,_|_| |_\_/ \__,_|_|_|\_\
12
+ ```
13
+
14
+ [![PyPI version](https://img.shields.io/pypi/v/lantalk)](https://pypi.org/project/lantalk/)
15
+ [![Python](https://img.shields.io/pypi/pyversions/lantalk)](https://pypi.org/project/lantalk/)
16
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
17
+
18
+ ---
19
+
20
+ ## What is LanTalk?
21
+
22
+ LanTalk lets people on the **same Wi-Fi or LAN** chat instantly — no accounts, no internet, no servers in the cloud. One person runs `lantalk` and starts a server; everyone else runs `lantalk` and joins. That's it.
23
+
24
+ - Works on school networks, home networks, offices, hackathons
25
+ - Pure Python stdlib — nothing to `pip install` beyond the package itself
26
+ - Clients auto-discover the server via UDP broadcast (no IP typing required)
27
+
28
+ ---
29
+
30
+ ## Features
31
+
32
+ | | |
33
+ |---|---|
34
+ | 🔍 **Auto-discovery** | UDP beacon finds servers on your LAN automatically |
35
+ | 🔐 **Password auth** | Optional server password with SHA-256 hashing |
36
+ | 👤 **Username dedup** | Two people can't use the same name simultaneously |
37
+ | 💬 **Private messages** | `/pm <user> <message>` — end-to-end on the wire |
38
+ | 🛡 **Rate limiting** | Spammers get warned then kicked (10 msg / 5 s) |
39
+ | ⏱ **Idle timeouts** | Dead sockets cleaned up after 5 minutes of silence |
40
+ | 🚫 **Persistent bans** | Banned IPs survive server restarts via `bans.json` |
41
+ | 🔇 **Full validation** | Every message checked for type and field constraints |
42
+ | 📝 **Structured logging** | Console + `lantalk.log` file, levels DEBUG/INFO/WARNING |
43
+ | ⚡ **Pure asyncio** | Single event loop — no threads, no race conditions |
44
+
45
+ ---
46
+
47
+ ## Install
48
+
49
+ ```bash
50
+ pip install lantalk
51
+ ```
52
+
53
+ Python 3.10+ required. No third-party dependencies.
54
+
55
+ ### From source
56
+
57
+ ```bash
58
+ git clone https://github.com/yourusername/lantalk
59
+ cd lantalk
60
+ pip install -e ".[dev]"
61
+ ```
62
+
63
+ ---
64
+
65
+ ## Quick start
66
+
67
+ ### 1 — Start a server (one person does this)
68
+
69
+ ```
70
+ $ lantalk
71
+
72
+ [1] Start a Server
73
+ [2] Join as Client
74
+
75
+ Choose (1 or 2): 1
76
+ Port (default 5050):
77
+ Server display name: Alice
78
+ Set password (leave blank for none): secret
79
+
80
+ ══════════════════════════════════════════════════════
81
+ LanTalk Server v2.0.0 — Alice
82
+ Listening on 192.168.1.5:5050
83
+ Discovery beacon active (UDP 5051)
84
+ Password protection: ON
85
+ ══════════════════════════════════════════════════════
86
+ ```
87
+
88
+ ### 2 — Join as a client (everyone else)
89
+
90
+ ```
91
+ $ lantalk
92
+
93
+ [1] Start a Server
94
+ [2] Join as Client
95
+
96
+ Choose (1 or 2): 2
97
+ Scanning for LanTalk servers…
98
+ Found 1 server(s):
99
+
100
+ [1] 192.168.1.5:5050
101
+ [m] Enter manually
102
+
103
+ Choose server: 1
104
+ Display name: Bob
105
+ Password: secret
106
+
107
+ ══════════════════════════════════════════════════════
108
+ LanTalk Client v2.0.0 — Bob
109
+ Connected to 192.168.1.5:5050
110
+ Commands: /users /pm <user> <msg> /quit
111
+ ══════════════════════════════════════════════════════
112
+ [Bob | lantalk] > Hey everyone!
113
+ [14:22] Alice: Welcome Bob!
114
+ [Bob | lantalk] > /pm Alice just between us 👋
115
+ [Bob | lantalk] > /users
116
+ [14:23] *** Online: Alice, Bob, Carol ***
117
+ [Bob | lantalk] >
118
+ ```
119
+
120
+ ---
121
+
122
+ ## Commands
123
+
124
+ ### Client commands
125
+
126
+ | Command | Description |
127
+ |---------|-------------|
128
+ | `/users` | List all connected users |
129
+ | `/pm <user> <message>` | Send a private message |
130
+ | `/quit` | Disconnect and exit |
131
+
132
+ ### Server console commands
133
+
134
+ | Command | Description |
135
+ |---------|-------------|
136
+ | `/users` | List connected users |
137
+ | `/stats` | Show connection count and ban list size |
138
+ | `/kick <user>` | Disconnect a user |
139
+ | `/ban <user>` | Ban a user's IP (persisted to `bans.json`) |
140
+ | `/bans` | Show all banned IPs |
141
+ | `/unban <ip>` | Remove an IP from the ban list |
142
+ | `/help` | Show this list |
143
+ | `/quit` | Shut down the server |
144
+ | *(anything else)* | Broadcast as a server message to all clients |
145
+
146
+ ---
147
+
148
+ ## Architecture
149
+
150
+ ```
151
+ ┌──────────────────────────────────────────────────────────────┐
152
+ │ LAN (e.g. 192.168.1.0/24) │
153
+ │ │
154
+ │ ┌────────────────────────────────────┐ │
155
+ │ │ LanTalkServer (pure asyncio) │ │
156
+ │ │ │◄─── TCP :5050 ───┐ │
157
+ │ │ _discovery_beacon() ─────────────┼──── UDP bcast │ │
158
+ │ │ asyncio coroutine, no threads │ every 2 s │ │
159
+ │ │ │ │ │
160
+ │ │ per-client _RateLimiter │ │ │
161
+ │ │ _validate() on every message │ │ │
162
+ │ │ asyncio.wait_for() timeouts │ │ │
163
+ │ │ bans.json (persistent) │ │ │
164
+ │ │ lantalk.log (structured) │ │ │
165
+ │ └────────────────────────────────────┘ │ │
166
+ │ │ │
167
+ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┴─┐ │
168
+ │ │ Client A │ │ Client B │ │ Client C │ │
169
+ │ │ UDP discover │ │ UDP discover │ │ manual IP entry │ │
170
+ │ │ asyncio │ │ asyncio │ │ asyncio │ │
171
+ │ └──────────────┘ └──────────────┘ └────────────────────┘ │
172
+ └──────────────────────────────────────────────────────────────┘
173
+
174
+ Message flow (post-auth):
175
+ Client ──JSON──► Server ──broadcast JSON──► all other Clients
176
+ └──(PM)──────────► one Client
177
+ ```
178
+
179
+ ### Concurrency model
180
+
181
+ Everything runs in **one asyncio event loop** — no `threading.Thread`, no locks between threads, no shared mutable state across OS threads. The only `asyncio.Lock` is used to guard the `_clients` dict between concurrent coroutines.
182
+
183
+ ### JSON wire protocol
184
+
185
+ Every message is a single UTF-8 JSON line terminated with `\n`.
186
+
187
+ ```jsonc
188
+ // Server → Client: auth challenge
189
+ {"type": "auth_request", "ts": "14:22", "needs_password": true}
190
+
191
+ // Client → Server: credentials
192
+ {"username": "Bob", "password": "secret"}
193
+
194
+ // Server → Client: success / failure
195
+ {"type": "auth_ok", "ts": "…", "username": "Bob", "server_name": "Alice"}
196
+ {"type": "auth_fail", "ts": "…", "reason": "Username already taken."}
197
+
198
+ // Client → Server: chat message
199
+ {"type": "message", "text": "Hello!"}
200
+
201
+ // Server → all clients: broadcast
202
+ {"type": "message", "ts": "14:22", "user": "Bob", "text": "Hello!"}
203
+
204
+ // Server → one client: private message
205
+ {"type": "pm", "ts": "14:22", "from_user": "Alice", "text": "hey"}
206
+
207
+ // Server → clients: system event
208
+ {"type": "system", "ts": "14:22", "text": "Bob joined from 192.168.1.10."}
209
+ ```
210
+
211
+ ---
212
+
213
+ ## Security notes
214
+
215
+ - Passwords are **never stored or sent in plaintext**. The server stores a SHA-256 hash; clients send the raw password only during the auth handshake (upgrade to TLS in v3 is planned).
216
+ - Banned IPs are written to `bans.json` in the server's working directory and reloaded on every start.
217
+ - Rate limiting: each client is capped at **10 messages per 5 seconds**. Exceeding this sends a warning; repeat offences kick the user.
218
+ - Usernames are limited to 24 alphanumeric/underscore/hyphen characters.
219
+ - All incoming messages are schema-validated before processing; malformed JSON is silently dropped.
220
+
221
+ ---
222
+
223
+ ## Logging
224
+
225
+ LanTalk writes structured logs to both the terminal and `lantalk.log`:
226
+
227
+ ```
228
+ [14:22:01] INFO Server started on 192.168.1.5:5050
229
+ [14:22:15] INFO Bob joined from 192.168.1.10
230
+ [14:23:44] WARNING Carol hit rate limit
231
+ [14:25:01] INFO Kicked Dave
232
+ [14:25:03] INFO Banned Dave (192.168.1.22)
233
+ ```
234
+
235
+ Set `LANTALK_LOG_LEVEL=DEBUG` to see per-message traces.
236
+
237
+ ---
238
+
239
+ ## Running tests
240
+
241
+ ```bash
242
+ pip install -e ".[dev]"
243
+ pytest -v
244
+ ```
245
+
246
+ ---
247
+
248
+ ## Changelog
249
+
250
+ ```
251
+ 2.0.0 — pure asyncio (no threads), validation, rate limiting,
252
+ timeouts, persistent bans, structured logging, v2 prompt
253
+ 1.1.0 — asyncio rewrite, UDP discovery, JSON protocol, auth, commands, pytest
254
+ 1.0.0 — initial: threading, basic TCP, plain-text protocol
255
+ ```
256
+
257
+ ---
258
+
259
+ ## Roadmap
260
+
261
+ - [ ] TLS encryption (v3)
262
+ - [ ] File transfer (`/send file.pdf`)
263
+ - [ ] Web UI mode (`http://localhost:5050`)
264
+ - [ ] Plugin system (`@lantalk.plugin`)
265
+
266
+ ---
267
+
268
+ ## License
269
+
270
+ MIT © Ezra
@@ -0,0 +1,2 @@
1
+ """LanTalk — terminal-based LAN chat."""
2
+ __version__ = "1.1.0"
@@ -0,0 +1,54 @@
1
+ """
2
+ lantalk.cli
3
+ -----------
4
+ Entry point for the `lantalk` command.
5
+ """
6
+
7
+ import sys
8
+ from lantalk.server import run_server, DEFAULT_PORT as SERVER_PORT
9
+ from lantalk.client import run_client, DEFAULT_PORT as CLIENT_PORT
10
+
11
+ VERSION = "2.0.0"
12
+
13
+ BANNER = r"""
14
+ _ _____ _ _
15
+ | | |_ _| | | |
16
+ | | __ _ _ __ | | __ _| | | __
17
+ | | / _` | '_ \ | |/ _` | | |/ /
18
+ | |___| (_| | | | || | (_| | | <
19
+ |______\__,_|_| |_\_/ \__,_|_|_|\_\
20
+
21
+ LAN chat — instant, private, no internet needed.
22
+ """
23
+
24
+
25
+ def _color(text: str, code: str) -> str:
26
+ return f"\033[{code}m{text}\033[0m"
27
+
28
+
29
+ def main() -> None:
30
+ print(_color(BANNER, "1;35"))
31
+ print(_color(f" v{VERSION} • pure asyncio • zero runtime dependencies\n", "35"))
32
+
33
+ print(" [1] Start a Server")
34
+ print(" [2] Join as Client")
35
+ print()
36
+
37
+ while True:
38
+ choice = input("Choose (1 or 2): ").strip()
39
+ if choice in ("1", "2"):
40
+ break
41
+ print(_color("Please enter 1 or 2.", "31"))
42
+
43
+ print()
44
+
45
+ if choice == "1":
46
+ port_in = input(f"Port (default {SERVER_PORT}): ").strip()
47
+ port = int(port_in) if port_in.isdigit() else SERVER_PORT
48
+ run_server(port=port)
49
+ else:
50
+ run_client(default_port=CLIENT_PORT)
51
+
52
+
53
+ if __name__ == "__main__":
54
+ main()