diff --git a/LTS.py b/LTS.py index 5d014db..bf01acb 100644 --- a/LTS.py +++ b/LTS.py @@ -1,6 +1,10 @@ #!/usr/bin/env python3 -# TouchFish LTS Client/Server Unified Program (Final Release, Version 4) + + + + +# TouchFish LTS Client/Server Unified Program (Security Updates, Version 4) @@ -9,7 +13,7 @@ """ # TouchFish 协议文档 -本协议文档版本:v2.4.0 +本协议文档版本:v2.6.0 本协议分为三个部分:`Gate`,`Chat`,`Misc`。 @@ -19,6 +23,10 @@ # 协议更新日志 +- Protocol v2.6.0 (TouchFish v4.9.0) + - 恢复 v2.3.0 的字段更改 +- Protocol v2.5.0 (TouchFish v4.8.0) + - 撤销 v2.3.0 的字段更改 - Protocol v2.4.0 (TouchFish v4.7.0) - 在 MISC.START 添加 stamp 字段 - Protocol v2.3.0 (TouchFish v4.6.0) @@ -111,7 +119,7 @@ - `type`: `"GATE.CLIENT_REQUEST.LOG"` - `time`: 同上。 -- `ip`: 客户端 IP 地址与端口。 +- `ip`: 客户端 IP 地址与端口。 - `username`: 用户名。 - `uid`: 用户 ID。 @@ -142,7 +150,7 @@ 当用户状态变更时,服务端进行广播。 -- `type`: `"GATE.STATUS_CHANGE.ANNOUNCE"` +- `type`: `"GATE.STATUS_CHANGE.ANNOUNCE"` - `status`: 新状态。 - `uid`: 被变更状态的用户 ID。 @@ -152,9 +160,9 @@ 服务端将用户状态变更事件写入日志。 -- `type`: 固定为 `"GATE.STATUS_CHANGE.LOG"`。 -- `time`: 同上。 -- `status`: 新状态。(`Pending` 状态和 `Root` 状态不会出现) +- `type`: 固定为 `"GATE.STATUS_CHANGE.LOG"`。 +- `time`: 同上。 +- `status`: 新状态。(`Pending` 状态和 `Root` 状态不会出现) - `uid`: 被操作用户的用户 ID。 - `operator`: 操作者的用户 ID。 @@ -172,9 +180,9 @@ - `type`: `"CHAT.SEND"` - `filename`: 文件名。若发送的是普通文本消息,则为空字符串 `""`;若发送文件,则为原始文件名。(下同) -- `content`: 若为消息,则为原始文本内容;若为文件,则为文件内容的 Base64 编码字符串。(下同) +- `content`: 若为消息,则为原始文本内容;若为文件,则为文件内容的 Base64 编码字符串。(下同) - `to`: 目标接收者,可能取值包括:(下同) - - `-2`:广播给所有在线用户(相较于普通发送有特殊提示); + - `-2`:广播给所有在线用户(相较于普通发送有特殊提示); - `-1`:发送给所有在线用户; - 非负整数:私聊给拥有相应用户 ID 的用户。 @@ -184,7 +192,7 @@ 服务端将消息转发给目标客户端。 -- `type`: `"CHAT.RECEIVE"` +- `type`: `"CHAT.RECEIVE"` - `from`: 发送者的用户 ID。(下同) - `order`: 消息编号,可能取值包括:(下同) - 正整数:普通文本消息; @@ -202,7 +210,7 @@ - `type`: `"CHAT.LOG"` - `time`: 同上。 - `from`: 同上。 -- `order`: 同上。 +- `order`: 同上。 - `filename`: 同上。 - `content`: 若为消息,则为原始文本内容;若为文件,则为空字符串 `""`。(为了防止日志文件过大,具体的文件内容会单独存储) - `to`: 同上。 @@ -215,14 +223,14 @@ ## 3.1 Start -`{ type: "MISC.START", time: time, stamp: number, server_version: string, config: JSON }` +`{ type: "MISC.START", time: time, stamp: number, version: string, config: JSON }` 程序将启动时的启动参数写入日志。 - `type`: `"MISC.START"` -- `time`: 同上。 +- `time`: 同上。 - `stamp`: 用于指定文件保存路径,取启动时的 UNIX 时间戳乘 `10 ** 6` 后向下取整。 -- `server_version`: 字符串,表示服务端程序版本。(下同) +- `version`: 字符串,表示服务端程序版本。(下同) - `config`: JSON 对象,表示启动参数。(具体格式详见代码,下同) ## 3.2 Data @@ -237,7 +245,7 @@ - `config`: 同上。 - `users`: 用户列表,每个元素为: - `username`: 用户名; - - `status`: 同上。 + - `status`: 同上。 - `chat_history`: 历史聊天记录,每条记录包含:(不包含私聊记录和文件发送记录) - `time`: 同上; - `order`:同上; @@ -324,7 +332,7 @@ 服务端将配置修改事件写入日志。 - `type`: `"MISC.CONFIG.LOG"` -- `time`: 同上。 +- `time`: 同上。 - `key`: 同上。 - `value`: 同上。 - `operator`: 执行修改操作的用户 ID。 @@ -354,7 +362,7 @@ import time # 程序版本 -VERSION = "v4.7.0" +VERSION = "v4.9.0" # 用于客户端解析协议 1.2 RESULTS = \ @@ -421,7 +429,7 @@ # 需要指出的是,第五部分中会给 username 字段 # 的默认值后面加上一个随机六位数作为后缀, # 形成形如 "user123456" 的用户名 -DEFAULT_CLIENT_CONFIG = {"side": "Client", "ip": "touchfish.xin", "port": 7001, "username": "user"} +DEFAULT_CLIENT_CONFIG = {"side": "Client", "ip": "touchfish.xin", "port": 11451, "username": "user"} # 默认服务端配置(side 和 general.* 必须在启动时指定): """ @@ -464,7 +472,7 @@ # 中指定的服务端用户名和所发送的文件的内容; # message.max_length 参数以「字符 (Unicode 码点) 个数」为准, # 例如「你好」算作 2 个字符; -# message.max_length 参数以「字节个数」为准, +# file.max_size 参数以「字节个数」为准, # 例如 UTF-8 格式的文本「你好」算作 6 个字节 CONFIG_TYPE_CHECK_TABLE = \ { @@ -516,12 +524,12 @@ # 缩写表 ABBREVIATION_TABLE = \ { - "D": "dashboard", "F": "distribute", "Q": "evaluate", "E": "exit", "L": "flood", + "D": "dashboard", "F": "distribute", "Q": "evaluate", "E": "exit", "L": "flood", "H": "help", "S": "send", "J": "shell", "T": "transfer", "P": "whisper", "I+": "ban ip add", "I-": "ban ip remove", "W+": "ban words add", "W-": "ban words remove", "B": "broadcast", "C": "config", "G+": "doorman accept", "G-": "doorman reject", "K": "kick", "A+": "admin add", "A-": "admin remove", "V": "save", - "d": "dashboard", "f": "distribute", "q": "evaluate", "e": "exit", "l": "flood", + "d": "dashboard", "f": "distribute", "q": "evaluate", "e": "exit", "l": "flood", "h": "help", "s": "send", "j": "shell", "t": "transfer", "p": "whisper", "i+": "ban ip add", "i-": "ban ip remove", "w+": "ban words add", "w-": "ban words remove", "b": "broadcast", "c": "config", "g+": "doorman accept", "g-": "doorman reject", "k": "kick", @@ -1001,7 +1009,7 @@ def read(): global buffer while True: try: - my_socket.setblocking(False) + my_socket.setblocking(False) # 再次显式设置为非阻塞模式,避免不必要的问题 chunk = my_socket.recv(131072).decode("utf-8") if not chunk: break @@ -1031,7 +1039,7 @@ def get_message(): partial_message = {key: value for key, value in message.items()} partial_message["content"] = "" log_queue.put(json.dumps(partial_message)) - else: + else: # filename 字段为空(或者 filename 字段根本不存在),表明不是文件 impossible_value = message["impossible_key"] # 故意引发 KeyError except KeyError: @@ -1316,7 +1324,7 @@ def do_config(arg, verbose=True, by=-1): except: printc(verbose, "指令格式不正确,请重试。") return - + printc(verbose, "操作成功。") def do_ban(arg, verbose=True, by=-1): @@ -1885,7 +1893,11 @@ def thread_gate(): data = "" while True: try: - data += conntmp.recv(131072).decode("utf-8") + conntmp.setblocking(False) # 再次显式设置为非阻塞模式,避免不必要的问题 + chunk = conntmp.recv(131072).decode("utf-8") + if not chunk: + raise + data += chunk except: break @@ -2059,7 +2071,7 @@ def thread_send(): # 先按文件处理 if not message["content"]["filename"]: # filename 字段为空(或者 filename 字段根本不存在),表明不是文件 impossible_value = message["content"]["impossible_key"] # 故意引发 KeyError - with open(message["content"]["filename"], "rb") as f: + with open(message["content"]["content"], "rb") as f: file_data = f.read() # 读取 do_distribute 或 do_transfer 函数先前写入到磁盘的对应文件 message["content"]["content"] = base64.b64encode(file_data).decode("utf-8") # 将 content 字段覆写为正确值 token = json.dumps(message["content"]) + "\n" @@ -2293,6 +2305,11 @@ def main(): os.system("") # 对 Windows 尝试开启 ANSI 转义字符(带颜色文本)支持 clear_screen() + prints("我们即将推出 TouchFish v5,敬请期待!", "magenta") + prints("服务端 Github 仓库:https://github.com/2044-space-elevator/TFV5_server", "magenta") + prints("客户端 Github 仓库:https://github.com/ILoveScratch2/TouchFish-Client", "magenta") + print() + if config_read_result == "OK": prints("配置文件 config.json 读取成功!", "yellow") if config_read_result == "Not found": diff --git a/PKGBUILD b/PKGBUILD index 45a6636..f5674f8 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: TouchFish Community pkgname=touchfish -pkgver=4.7.0 +pkgver=4.9.0 pkgrel=1 pkgdesc="FOSS multi-distribution LAN chatting tool" arch=('any') diff --git a/README.md b/README.md index c46eecc..7b1fc5f 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ > [!WARNING] > **这是 TouchFish v4 版本,自 v4 开始不再向前兼容 v1 - v3。** > -> **根据规划,此版本(v4.7.0)是 TouchFish v4 的最后一个子版本。TouchFish v5 正在施工,[链接](https://github.com/2044-space-elevator/TFV5_server)。下一版本预计将进入 v5。** +> **根据规划,此版本(v4.9.0)是 TouchFish v4 的最后一个子版本。TouchFish v5 正在施工,[链接](https://github.com/2044-space-elevator/TFV5_server)。下一版本预计将进入 v5。** > [!IMPORTANT] > **重要通知:贡献者须知** @@ -43,9 +43,9 @@ > (这里的命令只针对 Linux 用户) > > 不建议下载预编译的二进制文件,建议通过源代码部署 -> `wget https://github.com/2044-space-elevator/TouchFish/releases/download/v4.7.0/LTS.py && python3 LTS.py` +> `wget https://github.com/2044-space-elevator/TouchFish/releases/download/v4.9.0/LTS.py && python3 LTS.py` > -> (也可以通过 @ILoveScratch2 提供的镜像站,但是截至 2026/2/23 只更新到了 v4.6 版本:`wget https://mirror.ilovescratch.us.ci/api/net/379814722/LTS.py && python3 LTS.py`) +> (也可以通过 @ILoveScratch2 提供的镜像站,但是截至 2026/6/17 只更新到了 v4.7.0 版本:`wget https://mirror.ilovescratch.us.ci/api/net/183301217/LTS.py && python3 LTS.py`) 1. **获取内网 IP 地址**: - **Windows**: 命令提示符执行 `ipconfig`,查找 "无线局域网适配器 WLAN" 下的 "IPv4 地址" @@ -143,7 +143,7 @@ TouchFish 拥有丰富的衍生版本生态系统,满足不同用户需求: > 标 * 的版本可能需要自行编译、直接运行代码或缺少预编译包。 > -> 标 ^ 的版本可能与 LTS v4.6.0/v4.7.0 存在少量兼容性问题,此时建议使用 LTS v4.3.3。 +> 标 ^ 的版本与 LTS v4.9.0 存在兼容性问题,建议使用 LTS v4.8.0。 ---