v10: /color command to reshuffle user colors (web + terminal)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
38
chat.py
38
chat.py
@@ -25,7 +25,7 @@ import html
|
|||||||
import urllib.parse
|
import urllib.parse
|
||||||
|
|
||||||
PORT = 9999
|
PORT = 9999
|
||||||
VERSION = "9"
|
VERSION = "10"
|
||||||
TUNNEL_TARGETS = {
|
TUNNEL_TARGETS = {
|
||||||
"parspack": ("185.208.174.152", 22),
|
"parspack": ("185.208.174.152", 22),
|
||||||
"mequ": ("188.213.68.133", 2022),
|
"mequ": ("188.213.68.133", 2022),
|
||||||
@@ -149,13 +149,23 @@ const USER_COLORS = [
|
|||||||
'#ffb74d', '#aed581', '#f06292', '#4dd0e1'
|
'#ffb74d', '#aed581', '#f06292', '#4dd0e1'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
let colorSeed = 0; // bump this to rearrange colors
|
||||||
|
|
||||||
function userColor(name) {
|
function userColor(name) {
|
||||||
if (name === $name.value.trim()) return '#4ade80';
|
if (name === $name.value.trim()) return '#4ade80';
|
||||||
let h = 0;
|
let h = colorSeed;
|
||||||
for (let i = 0; i < name.length; i++) h = ((h << 5) - h + name.charCodeAt(i)) | 0;
|
for (let i = 0; i < name.length; i++) h = ((h << 5) - h + name.charCodeAt(i)) | 0;
|
||||||
return USER_COLORS[Math.abs(h) % USER_COLORS.length];
|
return USER_COLORS[Math.abs(h) % USER_COLORS.length];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function reshuffleColors() {
|
||||||
|
colorSeed = Math.floor(Math.random() * 100000);
|
||||||
|
// re-render all messages
|
||||||
|
const msgs = document.querySelectorAll('.msg');
|
||||||
|
// can't easily re-render, so just note it applies to new messages
|
||||||
|
addMsg({ts: Date.now()/1000, user: '***', text: 'Colors reshuffled!'});
|
||||||
|
}
|
||||||
|
|
||||||
function esc(s) {
|
function esc(s) {
|
||||||
const d = document.createElement('div');
|
const d = document.createElement('div');
|
||||||
d.textContent = s;
|
d.textContent = s;
|
||||||
@@ -217,6 +227,13 @@ function send() {
|
|||||||
const text = $input.value.trimEnd();
|
const text = $input.value.trimEnd();
|
||||||
const name = $name.value.trim() || 'anon';
|
const name = $name.value.trim() || 'anon';
|
||||||
if (!text) return;
|
if (!text) return;
|
||||||
|
// Local commands
|
||||||
|
if (text === '/colors' || text === '/color') {
|
||||||
|
reshuffleColors();
|
||||||
|
$input.value = '';
|
||||||
|
$input.style.height = 'auto';
|
||||||
|
return;
|
||||||
|
}
|
||||||
fetch('/chat/send', {
|
fetch('/chat/send', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||||
@@ -723,6 +740,18 @@ class ChatClient:
|
|||||||
self.reader: asyncio.StreamReader | None = None
|
self.reader: asyncio.StreamReader | None = None
|
||||||
self.writer: asyncio.StreamWriter | None = None
|
self.writer: asyncio.StreamWriter | None = None
|
||||||
self.running = True
|
self.running = True
|
||||||
|
self.color_seed = 0
|
||||||
|
|
||||||
|
def get_color(self, username: str) -> int:
|
||||||
|
"""Color pair for username, affected by color_seed."""
|
||||||
|
if username == "***":
|
||||||
|
return CP_SYSTEM
|
||||||
|
if username == self.name:
|
||||||
|
return CP_MY_NAME
|
||||||
|
h = self.color_seed
|
||||||
|
for c in username:
|
||||||
|
h = ((h << 5) - h + ord(c)) & 0xFFFFFFFF
|
||||||
|
return 10 + (h % len(OTHER_CURSES_COLORS))
|
||||||
|
|
||||||
def notify(self, msg: dict):
|
def notify(self, msg: dict):
|
||||||
"""Send terminal bell + update title for messages from others."""
|
"""Send terminal bell + update title for messages from others."""
|
||||||
@@ -742,7 +771,7 @@ class ChatClient:
|
|||||||
|
|
||||||
def add_message(self, msg: dict):
|
def add_message(self, msg: dict):
|
||||||
t = time.strftime("%H:%M", time.localtime(msg["ts"]))
|
t = time.strftime("%H:%M", time.localtime(msg["ts"]))
|
||||||
cp = user_color_pair(msg["user"], self.name)
|
cp = self.get_color(msg["user"])
|
||||||
if msg["user"] == "***":
|
if msg["user"] == "***":
|
||||||
self.messages.append((f" {t} {msg['text']}", CP_SYSTEM))
|
self.messages.append((f" {t} {msg['text']}", CP_SYSTEM))
|
||||||
elif msg.get("file_id"):
|
elif msg.get("file_id"):
|
||||||
@@ -850,6 +879,9 @@ class ChatClient:
|
|||||||
cmd = self.input_buf.strip()
|
cmd = self.input_buf.strip()
|
||||||
if cmd == "/quit":
|
if cmd == "/quit":
|
||||||
break
|
break
|
||||||
|
elif cmd in ("/color", "/colors"):
|
||||||
|
self.color_seed += 1
|
||||||
|
self.messages.append((" *** Colors reshuffled!", CP_SYSTEM))
|
||||||
elif cmd.startswith("/file "):
|
elif cmd.startswith("/file "):
|
||||||
await self.send_file(cmd[6:].strip())
|
await self.send_file(cmd[6:].strip())
|
||||||
else:
|
else:
|
||||||
|
|||||||
Reference in New Issue
Block a user