SPB Git

spb/admin-ka

Public

ajout de Groupe·Ka au sélecteur de projets du chat

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Simon-Pierre Boucher committed (Aug 20, 2026) parent 733d288 Browse files

32 changed files +6,069 −2

deleted .gitignore +0 −2
@@ -1,2 +0,0 @@
1−node_modules/
2−data/
added data/audit.jsonl +53 −0
@@ -0,0 +1,53 @@
1+{"ts":"2026-08-20T00:09:46.342Z","kind":"login_fail","ip":"70.25.239.68"}
2+{"ts":"2026-08-20T00:09:46.590Z","kind":"login_ok","ip":"70.25.239.68"}
3+{"ts":"2026-08-20T00:14:18.159Z","kind":"login_ok","ip":"70.25.239.68"}
4+{"ts":"2026-08-20T00:15:11.290Z","kind":"prompt","chatId":"3f52ef5c2d20f901","project":"/Users/simon-pierreboucher","node":"M3U96a","dir":"/Users/simon-pierreboucher","mode":"auto","prompt":"Réponds uniquement: PING-OK"}
5+{"ts":"2026-08-20T00:15:13.001Z","kind":"result","chatId":"3f52ef5c2d20f901","subtype":"success","cost":0.07691825000000001,"duration_ms":1462,"turns":1}
6+{"ts":"2026-08-20T00:15:32.184Z","kind":"prompt","chatId":"a605e4af3ff4ef68","project":"lou-ka@M3U96b","node":"M3U96b","dir":"~/apps/lou-ka","mode":"safe","prompt":"Exécute la commande git log --oneline -1 avec l outil Bash puis rapporte la sortie exacte. Ne fais rien d autre."}
7+{"ts":"2026-08-20T00:15:36.459Z","kind":"tool_use","chatId":"a605e4af3ff4ef68","tool":"Bash","input":"{\"command\":\"git log --oneline -1\",\"description\":\"Show last commit\"}"}
8+{"ts":"2026-08-20T00:15:38.505Z","kind":"result","chatId":"a605e4af3ff4ef68","subtype":"success","cost":0.050321950000000004,"duration_ms":5467,"turns":2}
9+{"ts":"2026-08-20T00:16:03.126Z","kind":"prompt","chatId":"a02996ca9e96e72a","project":"lou-ka@M3U96b","node":"M3U96b","dir":"~/apps/lou-ka","mode":"safe","prompt":"Exécute exactement cette commande avec l outil Bash: touch /tmp/adminka-perm-test-2026 && echo CREATED. Rapporte la sortie."}
10+{"ts":"2026-08-20T00:16:07.586Z","kind":"tool_use","chatId":"a02996ca9e96e72a","tool":"Bash","input":"{\"command\":\"touch /tmp/adminka-perm-test-2026 && echo CREATED\",\"description\":\"Create test file in /tmp and echo CREATED\"}"}
11+{"ts":"2026-08-20T00:16:12.089Z","kind":"result","chatId":"a02996ca9e96e72a","subtype":"success","cost":0.052153599999999994,"duration_ms":7840,"turns":2}
12+{"ts":"2026-08-20T00:19:02.513Z","kind":"login_ok","ip":"::ffff:127.0.0.1"}
13+{"ts":"2026-08-20T00:19:02.681Z","kind":"login_ok","ip":"70.25.239.68"}
14+{"ts":"2026-08-20T00:19:54.997Z","kind":"login_ok","ip":"2605:b100:122:c0a8:b11f:f73b:fe9d:bc14"}
15+{"ts":"2026-08-20T00:21:54.323Z","kind":"prompt","chatId":"cd7a17fc2311a9bb","project":"lou-ka@M3U96b","node":"M3U96b","dir":"~/apps/lou-ka","mode":"safe","prompt":"Execute exactement cette commande avec l outil Bash: touch /tmp/adminka-perm-test-2026 && echo CREATED. Rapporte la sortie. Aucun fichier de projet modifie donc pas de commit."}
16+{"ts":"2026-08-20T00:21:58.202Z","kind":"tool_use","chatId":"cd7a17fc2311a9bb","tool":"Bash","input":"{\"command\":\"touch /tmp/adminka-perm-test-2026 && echo CREATED\",\"description\":\"Create test file in /tmp\"}"}
17+{"ts":"2026-08-20T00:22:00.695Z","kind":"result","chatId":"cd7a17fc2311a9bb","subtype":"success","cost":0.05067714999999999,"duration_ms":5529,"turns":2}
18+{"ts":"2026-08-20T00:23:10.934Z","kind":"prompt","chatId":"81465e6bdd155087","project":"lou-ka@M3U96b","node":"M3U96b","dir":"~/apps/lou-ka","mode":"safe","prompt":"Execute exactement cette commande avec l outil Bash: touch /tmp/adminka-perm-test-2026 && echo CREATED. Rapporte la sortie."}
19+{"ts":"2026-08-20T00:23:14.693Z","kind":"tool_use","chatId":"81465e6bdd155087","tool":"Bash","input":"{\"command\":\"touch /tmp/adminka-perm-test-2026 && echo CREATED\",\"description\":\"Create test file in /tmp\"}"}
20+{"ts":"2026-08-20T00:23:14.704Z","kind":"permission_request","chatId":"81465e6bdd155087","tool":"Bash","input":"{\"command\":\"touch /tmp/adminka-perm-test-2026 && echo CREATED\",\"description\":\"Create test file in /tmp\"}"}
21+{"ts":"2026-08-20T00:23:14.770Z","kind":"permission_response","chatId":"81465e6bdd155087","requestId":"9f46fa5841aade3c","allow":true}
22+{"ts":"2026-08-20T00:23:16.945Z","kind":"result","chatId":"81465e6bdd155087","subtype":"success","cost":0.036749699999999996,"duration_ms":5149,"turns":2}
23+{"ts":"2026-08-20T00:23:46.614Z","kind":"prompt","chatId":"6b89119c0416877c","project":"lou-ka@M3U96b","node":"M3U96b","dir":"~/apps/lou-ka","mode":"safe","prompt":"Mémorise le mot de passe secret BANANE-42. Réponds uniquement: mémorisé."}
24+{"ts":"2026-08-20T00:23:55.311Z","kind":"result","chatId":"6b89119c0416877c","subtype":"success","cost":0.0320148,"duration_ms":7829,"turns":1}
25+{"ts":"2026-08-20T00:23:55.928Z","kind":"prompt","chatId":"6b89119c0416877c","project":"lou-ka@M3U96b","node":"M3U96b","dir":"~/apps/lou-ka","mode":"safe","prompt":"Quel est le mot de passe secret que je viens de te donner ? Réponds uniquement le mot."}
26+{"ts":"2026-08-20T00:23:59.032Z","kind":"result","chatId":"6b89119c0416877c","subtype":"success","cost":0.008705250000000001,"duration_ms":2670,"turns":1}
27+{"ts":"2026-08-20T00:26:41.877Z","kind":"login_ok","ip":"2605:b100:122:c0a8:b11f:f73b:fe9d:bc14"}
28+{"ts":"2026-08-20T00:54:46.997Z","kind":"prompt","chatId":"a3c0c1ae7ff9ae41","project":"lou-ka@M3U96b","node":"M3U96b","dir":"~/apps/lou-ka","mode":"safe","prompt":"Allo"}
29+{"ts":"2026-08-20T00:54:50.449Z","kind":"result","chatId":"a3c0c1ae7ff9ae41","subtype":"success","cost":0.041230199999999995,"duration_ms":2486,"turns":1}
30+{"ts":"2026-08-20T01:55:35.435Z","kind":"prompt","chatId":"aec35de8e2dfa1ce","project":"lou-ka@M3U96b","node":"M3U96b","dir":"~/apps/lou-ka","model":"opus","permMode":"bypass","prompt":"Quel modèle es-tu et dans quel répertoire de travail es-tu ? Vérifie avec pwd via Bash et donne aussi le nom du repo git. Réponds en 2 lignes."}
31+{"ts":"2026-08-20T01:55:39.139Z","kind":"tool_use","chatId":"aec35de8e2dfa1ce","tool":"Bash","input":"{\"command\":\"pwd && basename $(git rev-parse --show-toplevel)\",\"description\":\"Show working directory and git repo name\"}"}
32+{"ts":"2026-08-20T01:55:41.690Z","kind":"result","chatId":"aec35de8e2dfa1ce","subtype":"success","cost":0.115017,"duration_ms":5552,"turns":2}
33+{"ts":"2026-08-20T01:55:58.883Z","kind":"prompt","chatId":"aec35de8e2dfa1ce","project":"lou-ka@M3U96b","node":"M3U96b","dir":"~/apps/lou-ka","model":"haiku","permMode":"bypass","prompt":"Redis-moi quel modèle tu es maintenant, et rappelle en un mot ce que je t ai demandé au tour précédent."}
34+{"ts":"2026-08-20T01:56:02.883Z","kind":"result","chatId":"aec35de8e2dfa1ce","subtype":"success","cost":0.015552400000000001,"duration_ms":3759,"turns":1}
35+{"ts":"2026-08-20T01:56:27.868Z","kind":"prompt","chatId":"aec35de8e2dfa1ce","project":"lou-ka@M3U96b","node":"M3U96b","dir":"~/apps/lou-ka","model":"opus","permMode":"bypass","prompt":"Cite mot pour mot la toute première question que je t ai posée dans cette conversation."}
36+{"ts":"2026-08-20T01:56:29.892Z","kind":"result","chatId":"aec35de8e2dfa1ce","subtype":"success","cost":0.020039,"duration_ms":1777,"turns":1}
37+{"ts":"2026-08-20T01:56:52.618Z","kind":"prompt","chatId":"55675f90d1d9eb7f","project":"sorti-ka@M3U96a","node":"M3U96a","dir":"/Users/simon-pierreboucher/apps/sorti-ka","model":"opus","permMode":"bypass","prompt":"Exécute avec Bash exactement: sleep 90 && echo TERMINE-APRES-90S — puis réponds uniquement: FINI."}
38+{"ts":"2026-08-20T01:56:55.922Z","kind":"tool_use","chatId":"55675f90d1d9eb7f","tool":"Bash","input":"{\"command\":\"sleep 90 && echo TERMINE-APRES-90S\",\"description\":\"Sleep 90 seconds then echo\",\"timeout\":100000}"}
39+{"ts":"2026-08-20T01:56:58.785Z","kind":"tool_use","chatId":"55675f90d1d9eb7f","tool":"Bash","input":"{\"command\":\"sleep 90 && echo TERMINE-APRES-90S\",\"description\":\"Sleep 90 seconds then echo in background\",\"run_in_background\":true}"}
40+{"ts":"2026-08-20T01:57:01.018Z","kind":"tool_use","chatId":"55675f90d1d9eb7f","tool":"ToolSearch","input":"{\"query\":\"select:Monitor\",\"max_results\":1}"}
41+{"ts":"2026-08-20T01:57:09.054Z","kind":"tool_use","chatId":"55675f90d1d9eb7f","tool":"Monitor","input":"{\"command\":\"until grep -q TERMINE-APRES-90S /private/tmp/claude-501/-Users-simon-pierreboucher-apps-sorti-ka/8f7fb976-2d34-4eb5-bf9c-80d1ba388e7d/tasks/be9tfey63.output 2>/dev/null; do sleep 2; done; echo DONE\",\"description\":\"wait for sleep-90 background command to finish\",\"timeout_ms\":120000,\"persistent\":false}"}
42+{"ts":"2026-08-20T01:57:10.472Z","kind":"result","chatId":"55675f90d1d9eb7f","subtype":"success","cost":0.43205750000000004,"duration_ms":17578,"turns":5}
43+{"ts":"2026-08-20T01:58:35.144Z","kind":"prompt","chatId":"c6bf4c6c75817784","project":"lou-ka@M3U96b","node":"M3U96b","dir":"~/apps/lou-ka","model":"opus","permMode":"acceptEdits","prompt":"Crée le fichier docs/admin-ka-e2e.md avec ce contenu exact: ligne 1 \"# Test E2E Admin-Ka\", ligne 3 \"Validation du pilotage Claude Code via administration-ka.com — 2026-08-19.\" Puis git add docs/admin-ka-e2e.md, git commit -m \"docs: test E2E console Admin-Ka\" et git push origin main. Fichier de documentation seulement: NE redémarre PAS pm2, NE rebuild PAS."}
44+{"ts":"2026-08-20T01:58:39.222Z","kind":"tool_use","chatId":"c6bf4c6c75817784","tool":"Bash","input":"{\"command\":\"ls /Users/simon-pierreboucher/apps/lou-ka/docs 2>/dev/null || echo \\\"docs dir does not exist\\\"\",\"description\":\"Check if docs directory exists\"}"}
45+{"ts":"2026-08-20T01:58:41.972Z","kind":"tool_use","chatId":"c6bf4c6c75817784","tool":"Write","input":"{\"file_path\":\"/Users/simon-pierreboucher/apps/lou-ka/docs/admin-ka-e2e.md\",\"content\":\"# Test E2E Admin-Ka\\n\\nValidation du pilotage Claude Code via administration-ka.com — 2026-08-19.\\n\"}"}
46+{"ts":"2026-08-20T01:58:44.232Z","kind":"tool_use","chatId":"c6bf4c6c75817784","tool":"Bash","input":"{\"command\":\"git add docs/admin-ka-e2e.md && git commit -m \\\"docs: test E2E console Admin-Ka\\\" && git push origin main\",\"description\":\"Commit and push the docs file\"}"}
47+{"ts":"2026-08-20T01:58:44.290Z","kind":"permission_request","chatId":"c6bf4c6c75817784","tool":"Bash","input":"{\"command\":\"git add docs/admin-ka-e2e.md && git commit -m \\\"docs: test E2E console Admin-Ka\\\" && git push origin main\",\"description\":\"Commit and push the docs file\"}"}
48+{"ts":"2026-08-20T01:58:44.354Z","kind":"permission_response","chatId":"c6bf4c6c75817784","requestId":"13397bb8a4894ac9","allow":true,"always":true}
49+{"ts":"2026-08-20T01:58:46.639Z","kind":"result","chatId":"c6bf4c6c75817784","subtype":"success","cost":0.12456475,"duration_ms":10774,"turns":4}
50+{"ts":"2026-08-20T02:00:25.939Z","kind":"prompt","chatId":"352c98e9e9d31975","project":"lou-ka@M3U96b","node":"M3U96b","dir":"~/apps/lou-ka","model":"fable","permMode":"bypass","prompt":"Quel modèle es-tu exactement (ID) ? Une ligne."}
51+{"ts":"2026-08-20T02:00:31.512Z","kind":"result","chatId":"352c98e9e9d31975","subtype":"success","cost":0.10990075,"duration_ms":4957,"turns":1}
52+{"ts":"2026-08-20T04:16:58.224Z","kind":"prompt","chatId":"21d6c1690bd84a05","project":"crea-ka@M3U96b","node":"M3U96b","dir":"~/apps/crea-ka","model":"fable","permMode":"default","prompt":"Allo"}
53+{"ts":"2026-08-20T04:17:05.971Z","kind":"result","chatId":"21d6c1690bd84a05","subtype":"success","cost":0.15040725000000002,"duration_ms":6960,"turns":1}
added data/backend.err.log +0 −0
added data/backend.log +9 −0
@@ -0,0 +1,9 @@
1+admin-ka backend sur http://127.0.0.1:3300
2+admin-ka backend sur http://0.0.0.0:3300
3+admin-ka backend sur port 3300 (dual-stack)
4+admin-ka backend sur port 3300 (dual-stack)
5+admin-ka backend sur port 3300 (dual-stack)
6+admin-ka backend sur port 3300 (dual-stack)
7+admin-ka v2 sur port 3300 (dual-stack)
8+admin-ka v2 sur port 3300 (dual-stack)
9+admin-ka v2 sur port 3300 (dual-stack)
added data/chats.json +21 −0
@@ -0,0 +1,21 @@
1+[
2+ {
3+ "id": "21d6c1690bd84a05",
4+ "title": "Allo",
5+ "projectId": "crea-ka@M3U96b",
6+ "projectName": "Créa·Ka",
7+ "node": "M3U96b",
8+ "dir": "~/apps/crea-ka",
9+ "model": "fable",
10+ "permMode": "default",
11+ "claudeSessionId": "1a808aed-e9c3-4913-bef8-698d375e8789",
12+ "state": "idle",
13+ "totalCost": 0.15040725000000002,
14+ "turns": 1,
15+ "contextTokens": 39717,
16+ "alwaysAllow": [],
17+ "created": 1787199418217,
18+ "updated": 1787199426469,
19+ "lastModel": "claude-fable-5"
20+ }
21+]
\ No newline at end of file
added data/config.json +5 −0
@@ -0,0 +1,5 @@
1+{
2+ "salt": "c4b136cc7ecf11de11392c0e94754234",
3+ "passwordHash": "936110daf78afb40f2732f201199db9dd178942daad54823949e22db79e0b77f9e88f2b4dff589d3d14ecc0bf94576aa195925c3f9ccda7c7f3158ff05fffb40",
4+ "port": 3300
5+}
\ No newline at end of file
added data/eco.sqlite +0 −0

Binary file not shown.

added data/ngrok.err.log +0 −0
added data/ngrok.log +325 −0
@@ -0,0 +1,325 @@
1+t=2026-08-19T20:09:21-0400 lvl=info msg="no configuration paths supplied"
2+t=2026-08-19T20:09:21-0400 lvl=info msg="using configuration at default config path" path="/Users/simon-pierreboucher/Library/Application Support/ngrok/ngrok.yml"
3+t=2026-08-19T20:09:21-0400 lvl=info msg="open config file" path="/Users/simon-pierreboucher/Library/Application Support/ngrok/ngrok.yml" err=nil
4+t=2026-08-19T20:09:21-0400 lvl=info msg="FIPS 140 mode" enabled=false
5+t=2026-08-19T20:09:21-0400 lvl=warn msg="can't bind default web address, trying alternatives" obj=web addr=127.0.0.1:4040
6+t=2026-08-19T20:09:21-0400 lvl=info msg="starting web service" obj=web addr=127.0.0.1:40413 allow_hosts=[]
7+t=2026-08-19T20:09:21-0400 lvl=info msg="client session established" obj=tunnels.session
8+t=2026-08-19T20:09:21-0400 lvl=info msg="tunnel session started" obj=tunnels.session
9+t=2026-08-19T20:09:21-0400 lvl=info msg="update available" obj=updater
10+t=2026-08-19T20:09:21-0400 lvl=info msg="started tunnel" obj=tunnels name=command_line addr=http://localhost:3300 url=https://www.administration-ka.com
11+t=2026-08-19T20:09:46-0400 lvl=info msg="join connections" obj=join id=980a6d7c2d3b l=127.0.0.1:3300 r=70.25.239.68:60788
12+t=2026-08-19T20:09:46-0400 lvl=info msg="join connections" obj=join id=5c1f696a3a66 l=127.0.0.1:3300 r=70.25.239.68:60789
13+t=2026-08-19T20:09:46-0400 lvl=info msg="join connections" obj=join id=46fe0fc01d6f l=127.0.0.1:3300 r=70.25.239.68:60790
14+t=2026-08-19T20:09:46-0400 lvl=info msg="join connections" obj=join id=3bdd2daa6599 l=127.0.0.1:3300 r=70.25.239.68:60791
15+t=2026-08-19T20:09:46-0400 lvl=info msg="join connections" obj=join id=da42bfe0036b l=127.0.0.1:3300 r=70.25.239.68:60792
16+t=2026-08-19T20:10:55-0400 lvl=info msg="join connections" obj=join id=d5e06e3670a1 l=127.0.0.1:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:58680
17+t=2026-08-19T20:10:55-0400 lvl=info msg="join connections" obj=join id=b44c284a2628 l=127.0.0.1:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:58680
18+t=2026-08-19T20:10:55-0400 lvl=info msg="join connections" obj=join id=c7fc1f1d3815 l=127.0.0.1:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:58680
19+t=2026-08-19T20:10:55-0400 lvl=info msg="join connections" obj=join id=9db72a834f55 l=127.0.0.1:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:58680
20+t=2026-08-19T20:10:55-0400 lvl=info msg="join connections" obj=join id=448679569283 l=127.0.0.1:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:58680
21+t=2026-08-19T20:10:56-0400 lvl=info msg="join connections" obj=join id=9b4580c6a9d4 l=127.0.0.1:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:58681
22+t=2026-08-19T20:12:33-0400 lvl=info msg="join connections" obj=join id=898faed82b2a l=127.0.0.1:3300 r=70.25.239.68:61178
23+t=2026-08-19T20:12:33-0400 lvl=info msg="join connections" obj=join id=a2850fd431a7 l=127.0.0.1:3300 r=70.25.239.68:61178
24+t=2026-08-19T20:12:33-0400 lvl=info msg="join connections" obj=join id=50c2f8aff620 l=127.0.0.1:3300 r=70.25.239.68:61178
25+t=2026-08-19T20:12:33-0400 lvl=info msg="join connections" obj=join id=6689908fa5b8 l=127.0.0.1:3300 r=70.25.239.68:61178
26+t=2026-08-19T20:12:33-0400 lvl=info msg="join connections" obj=join id=4907f98b3412 l=127.0.0.1:3300 r=70.25.239.68:61178
27+t=2026-08-19T20:14:18-0400 lvl=info msg="join connections" obj=join id=966c9fd6bd2a l=127.0.0.1:3300 r=70.25.239.68:61178
28+t=2026-08-19T20:14:18-0400 lvl=info msg="join connections" obj=join id=f850e915d8df l=127.0.0.1:3300 r=70.25.239.68:61180
29+t=2026-08-19T20:14:43-0400 lvl=info msg="join connections" obj=join id=f0278a8f8868 l=127.0.0.1:3300 r=70.25.239.68:61182
30+t=2026-08-19T20:15:05-0400 lvl=info msg="join connections" obj=join id=2e09cfdeb763 l=127.0.0.1:3300 r=70.25.239.68:61178
31+t=2026-08-19T20:15:05-0400 lvl=info msg="join connections" obj=join id=ed38b337a25a l=127.0.0.1:3300 r=70.25.239.68:61178
32+t=2026-08-19T20:15:06-0400 lvl=info msg="join connections" obj=join id=501220e8b873 l=127.0.0.1:3300 r=70.25.239.68:61185
33+t=2026-08-19T20:15:11-0400 lvl=info msg="join connections" obj=join id=c10c89a96eee l=127.0.0.1:3300 r=76.70.60.50:49847
34+t=2026-08-19T20:15:32-0400 lvl=info msg="join connections" obj=join id=e6cabb676952 l=127.0.0.1:3300 r=76.70.60.50:49969
35+t=2026-08-19T20:16:03-0400 lvl=info msg="join connections" obj=join id=1ccabdbb46e7 l=127.0.0.1:3300 r=76.70.60.50:50066
36+t=2026-08-19T20:16:22-0400 lvl=info msg="join connections" obj=join id=b94bb62f7425 l=127.0.0.1:3300 r=70.25.239.68:61178
37+t=2026-08-19T20:16:39-0400 lvl=info msg="join connections" obj=join id=5b7063cfde4f l=127.0.0.1:3300 r=74.7.230.51:44558
38+t=2026-08-19T20:16:40-0400 lvl=info msg="join connections" obj=join id=381c043b7b39 l=127.0.0.1:3300 r=74.7.242.32:41364
39+t=2026-08-19T20:17:20-0400 lvl=info msg="join connections" obj=join id=6b9c1bd836f0 l=[::1]:3300 r=70.25.239.68:61194
40+t=2026-08-19T20:18:11-0400 lvl=info msg="join connections" obj=join id=cf5f66bce1c8 l=[::1]:3300 r=70.25.239.68:61178
41+t=2026-08-19T20:18:11-0400 lvl=info msg="join connections" obj=join id=d3de1b52cb3f l=[::1]:3300 r=70.25.239.68:61178
42+t=2026-08-19T20:18:11-0400 lvl=info msg="join connections" obj=join id=d57e107f07e6 l=[::1]:3300 r=70.25.239.68:61198
43+t=2026-08-19T20:19:01-0400 lvl=info msg="join connections" obj=join id=6a0b2df6e4b0 l=[::1]:3300 r=70.25.239.68:61201
44+t=2026-08-19T20:19:02-0400 lvl=info msg="join connections" obj=join id=b6d71e5db46a l=[::1]:3300 r=70.25.239.68:61044
45+t=2026-08-19T20:19:17-0400 lvl=info msg="join connections" obj=join id=f61b26ca5d4d l=[::1]:3300 r=70.25.239.68:61178
46+t=2026-08-19T20:19:17-0400 lvl=info msg="join connections" obj=join id=d4e6708ce744 l=[::1]:3300 r=70.25.239.68:61178
47+t=2026-08-19T20:19:18-0400 lvl=info msg="join connections" obj=join id=e4150d486b1a l=[::1]:3300 r=70.25.239.68:61203
48+t=2026-08-19T20:19:46-0400 lvl=info msg="join connections" obj=join id=35c2512ad178 l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:58937
49+t=2026-08-19T20:19:46-0400 lvl=info msg="join connections" obj=join id=33618c8ce7f2 l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:58937
50+t=2026-08-19T20:19:46-0400 lvl=info msg="join connections" obj=join id=a85b93644124 l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:58937
51+t=2026-08-19T20:19:46-0400 lvl=info msg="join connections" obj=join id=487f1f07757c l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:58937
52+t=2026-08-19T20:19:46-0400 lvl=info msg="join connections" obj=join id=e6d554cf2a8c l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:58937
53+t=2026-08-19T20:19:54-0400 lvl=info msg="join connections" obj=join id=d8d75780fb1f l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:58937
54+t=2026-08-19T20:19:55-0400 lvl=info msg="join connections" obj=join id=5fa348af28aa l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:58947
55+t=2026-08-19T20:20:01-0400 lvl=info msg="join connections" obj=join id=e0afa0f6fb8c l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:58937
56+t=2026-08-19T20:20:07-0400 lvl=info msg="join connections" obj=join id=a7bd0c32dbb1 l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:58937
57+t=2026-08-19T20:20:07-0400 lvl=info msg="join connections" obj=join id=1fe4ee89a34c l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:58949
58+t=2026-08-19T20:20:17-0400 lvl=info msg="join connections" obj=join id=2fa2930858a3 l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:58937
59+t=2026-08-19T20:20:17-0400 lvl=info msg="join connections" obj=join id=3d5cb3abf09d l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:58937
60+t=2026-08-19T20:20:18-0400 lvl=info msg="join connections" obj=join id=41778aa549bc l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:58951
61+t=2026-08-19T20:21:11-0400 lvl=info msg="join connections" obj=join id=71517d3ba713 l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:58952
62+t=2026-08-19T20:21:11-0400 lvl=info msg="join connections" obj=join id=9b7bf784f172 l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:58952
63+t=2026-08-19T20:21:11-0400 lvl=info msg="join connections" obj=join id=a578d46dd2a6 l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:58958
64+t=2026-08-19T20:21:13-0400 lvl=info msg="join connections" obj=join id=52e81ec32b77 l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:58959
65+t=2026-08-19T20:21:13-0400 lvl=info msg="join connections" obj=join id=eba92f75b634 l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:58961
66+t=2026-08-19T20:21:44-0400 lvl=info msg="join connections" obj=join id=7983c0607377 l=[::1]:3300 r=70.25.239.68:61212
67+t=2026-08-19T20:21:54-0400 lvl=info msg="join connections" obj=join id=a9c04db4a702 l=[::1]:3300 r=76.70.60.50:51559
68+t=2026-08-19T20:23:09-0400 lvl=info msg="join connections" obj=join id=ccbadafce458 l=[::1]:3300 r=70.25.239.68:61215
69+t=2026-08-19T20:23:10-0400 lvl=info msg="join connections" obj=join id=511151556827 l=[::1]:3300 r=76.70.60.50:51868
70+t=2026-08-19T20:23:46-0400 lvl=info msg="join connections" obj=join id=d96aabf566e9 l=[::1]:3300 r=76.70.60.50:51989
71+t=2026-08-19T20:24:00-0400 lvl=info msg="join connections" obj=join id=d000143fd634 l=[::1]:3300 r=70.25.239.68:61153
72+t=2026-08-19T20:24:00-0400 lvl=info msg="join connections" obj=join id=dc709ba7a1ea l=[::1]:3300 r=70.25.239.68:61154
73+t=2026-08-19T20:24:00-0400 lvl=info msg="join connections" obj=join id=a8b0cf15bb58 l=[::1]:3300 r=70.25.239.68:61155
74+t=2026-08-19T20:24:00-0400 lvl=info msg="join connections" obj=join id=238209481dab l=[::1]:3300 r=70.25.239.68:61156
75+t=2026-08-19T20:24:00-0400 lvl=info msg="join connections" obj=join id=416cec98c6f8 l=[::1]:3300 r=70.25.239.68:61157
76+t=2026-08-19T20:26:33-0400 lvl=info msg="join connections" obj=join id=c3ca6fc3d898 l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:59109
77+t=2026-08-19T20:26:33-0400 lvl=info msg="join connections" obj=join id=97fd39d6279c l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:59110
78+t=2026-08-19T20:26:33-0400 lvl=info msg="join connections" obj=join id=3144d5ecc517 l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:59109
79+t=2026-08-19T20:26:33-0400 lvl=info msg="join connections" obj=join id=fda1b5685aaf l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:59109
80+t=2026-08-19T20:26:33-0400 lvl=info msg="join connections" obj=join id=bb3c94e2c887 l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:59110
81+t=2026-08-19T20:26:41-0400 lvl=info msg="join connections" obj=join id=a972348ca626 l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:59109
82+t=2026-08-19T20:26:42-0400 lvl=info msg="join connections" obj=join id=1b6a44e6ae48 l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:59113
83+t=2026-08-19T20:26:50-0400 lvl=info msg="join connections" obj=join id=5251de2cc125 l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:59109
84+t=2026-08-19T20:27:36-0400 lvl=info msg="join connections" obj=join id=ef07095e8c87 l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:59118
85+t=2026-08-19T20:30:29-0400 lvl=info msg="join connections" obj=join id=2dcf5956dc4f l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:59165
86+t=2026-08-19T20:33:37-0400 lvl=info msg="join connections" obj=join id=2a382cc497af l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:59252
87+t=2026-08-19T20:35:01-0400 lvl=info msg="join connections" obj=join id=3ee68693eadd l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:59259
88+t=2026-08-19T20:35:17-0400 lvl=info msg="join connections" obj=join id=aad867620c1f l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:59264
89+t=2026-08-19T20:35:17-0400 lvl=info msg="join connections" obj=join id=e2c437bd2af1 l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:59264
90+t=2026-08-19T20:35:17-0400 lvl=info msg="join connections" obj=join id=e7037481d67b l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:59264
91+t=2026-08-19T20:35:18-0400 lvl=info msg="join connections" obj=join id=f3e024c4d121 l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:59266
92+t=2026-08-19T20:35:20-0400 lvl=info msg="join connections" obj=join id=d7f49ecb8491 l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:59267
93+t=2026-08-19T20:35:20-0400 lvl=info msg="join connections" obj=join id=1f94b4239ecb l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:59267
94+t=2026-08-19T20:35:20-0400 lvl=info msg="join connections" obj=join id=5f1e4aaa5900 l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:59267
95+t=2026-08-19T20:36:05-0400 lvl=info msg="join connections" obj=join id=1840b60abc91 l=[::1]:3300 r=76.70.60.50:52253
96+t=2026-08-19T20:36:05-0400 lvl=info msg="join connections" obj=join id=39978d0df1b1 l=[::1]:3300 r=76.70.60.50:52253
97+t=2026-08-19T20:36:05-0400 lvl=info msg="join connections" obj=join id=0675d310ee49 l=[::1]:3300 r=76.70.60.50:52253
98+t=2026-08-19T20:36:05-0400 lvl=info msg="join connections" obj=join id=0441920f031d l=[::1]:3300 r=76.70.60.50:52253
99+t=2026-08-19T20:36:05-0400 lvl=info msg="join connections" obj=join id=ad2bb07c72c7 l=[::1]:3300 r=76.70.60.50:52253
100+t=2026-08-19T20:36:11-0400 lvl=info msg="join connections" obj=join id=e4f01289a400 l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:59334
101+t=2026-08-19T20:37:55-0400 lvl=info msg="join connections" obj=join id=26a7a8124c46 l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:59477
102+t=2026-08-19T20:38:34-0400 lvl=info msg="join connections" obj=join id=cc87f89405c0 l=[::1]:3300 r=76.70.60.50:52255
103+t=2026-08-19T20:38:34-0400 lvl=info msg="join connections" obj=join id=29f427844065 l=[::1]:3300 r=76.70.60.50:52255
104+t=2026-08-19T20:40:01-0400 lvl=info msg="join connections" obj=join id=7589e76cd06b l=[::1]:3300 r=216.73.217.52:24133
105+t=2026-08-19T20:40:32-0400 lvl=info msg="join connections" obj=join id=c41da4e0fd39 l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:59637
106+t=2026-08-19T20:52:43-0400 lvl=info msg="join connections" obj=join id=a1c5936ba614 l=[::1]:3300 r=168.100.9.46:51230
107+t=2026-08-19T20:54:38-0400 lvl=info msg="join connections" obj=join id=ba6958a28f23 l=[::1]:3300 r=184.151.190.153:59714
108+t=2026-08-19T20:55:06-0400 lvl=info msg="join connections" obj=join id=ac42a620c819 l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:59945
109+t=2026-08-19T20:55:30-0400 lvl=info msg="join connections" obj=join id=dd2492d3e89b l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:59949
110+t=2026-08-19T20:55:59-0400 lvl=info msg="join connections" obj=join id=a4d3f7e1724b l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:59973
111+t=2026-08-19T20:57:40-0400 lvl=info msg="join connections" obj=join id=d37e9c52a598 l=[::1]:3300 r=[2605:b100:122:c0a8:b11f:f73b:fe9d:bc14]:59984
112+t=2026-08-19T21:13:35-0400 lvl=info msg="join connections" obj=join id=99a6b45518cb l=[::1]:3300 r=67.215.237.243:15001
113+t=2026-08-19T21:21:09-0400 lvl=info msg="join connections" obj=join id=38ffabd533b9 l=[::1]:3300 r=76.70.60.50:52371
114+t=2026-08-19T21:21:10-0400 lvl=info msg="join connections" obj=join id=95aa98ab08cd l=[::1]:3300 r=76.70.60.50:52371
115+t=2026-08-19T21:21:10-0400 lvl=info msg="join connections" obj=join id=8c28ce4993f6 l=[::1]:3300 r=76.70.60.50:52371
116+t=2026-08-19T21:21:10-0400 lvl=info msg="join connections" obj=join id=939c5e7192cd l=[::1]:3300 r=76.70.60.50:52371
117+t=2026-08-19T21:21:10-0400 lvl=info msg="join connections" obj=join id=79cf54ebe3ed l=[::1]:3300 r=76.70.60.50:52371
118+t=2026-08-19T21:26:47-0400 lvl=info msg="join connections" obj=join id=1fde653346ac l=[::1]:3300 r=95.181.238.176:60486
119+t=2026-08-19T21:26:47-0400 lvl=info msg="join connections" obj=join id=a94f1ca60038 l=[::1]:3300 r=188.214.125.44:38248
120+t=2026-08-19T21:26:47-0400 lvl=info msg="join connections" obj=join id=57c6a5fff414 l=[::1]:3300 r=158.173.101.49:49914
121+t=2026-08-19T21:26:48-0400 lvl=info msg="join connections" obj=join id=26ebdb20fbe1 l=[::1]:3300 r=45.154.153.3:49918
122+t=2026-08-19T21:26:48-0400 lvl=info msg="join connections" obj=join id=c6510d5a1891 l=[::1]:3300 r=191.96.168.41:45206
123+t=2026-08-19T21:26:48-0400 lvl=info msg="join connections" obj=join id=81d2d29cf0cc l=[::1]:3300 r=45.132.194.11:47250
124+t=2026-08-19T21:26:48-0400 lvl=info msg="join connections" obj=join id=fc693b0c9835 l=[::1]:3300 r=154.47.30.5:49884
125+t=2026-08-19T21:27:22-0400 lvl=info msg="join connections" obj=join id=045a389c786b l=[::1]:3300 r=62.210.198.226:49734
126+t=2026-08-19T21:27:24-0400 lvl=info msg="join connections" obj=join id=24cb416fd483 l=[::1]:3300 r=62.210.198.226:50897
127+t=2026-08-19T21:27:25-0400 lvl=info msg="join connections" obj=join id=d81277cb17d9 l=[::1]:3300 r=62.210.198.226:50897
128+t=2026-08-19T21:27:25-0400 lvl=info msg="join connections" obj=join id=d91f73084ed2 l=[::1]:3300 r=62.210.198.226:50897
129+t=2026-08-19T21:27:25-0400 lvl=info msg="join connections" obj=join id=de81fc49ba71 l=[::1]:3300 r=62.210.198.226:50897
130+t=2026-08-19T21:27:25-0400 lvl=info msg="join connections" obj=join id=17cbe828e617 l=[::1]:3300 r=62.210.198.226:50897
131+t=2026-08-19T21:27:25-0400 lvl=info msg="join connections" obj=join id=279f56968814 l=[::1]:3300 r=62.210.198.226:45102
132+t=2026-08-19T21:27:25-0400 lvl=info msg="join connections" obj=join id=26174e1522dd l=[::1]:3300 r=62.210.198.226:45102
133+t=2026-08-19T21:27:25-0400 lvl=info msg="join connections" obj=join id=a669475a9657 l=[::1]:3300 r=62.210.198.226:45102
134+t=2026-08-19T21:27:25-0400 lvl=info msg="join connections" obj=join id=a065a2dde61d l=[::1]:3300 r=62.210.198.226:45102
135+t=2026-08-19T21:27:25-0400 lvl=info msg="join connections" obj=join id=5af7c33f6ae0 l=[::1]:3300 r=62.210.198.226:45102
136+t=2026-08-19T21:27:30-0400 lvl=info msg="join connections" obj=join id=4720db600eaf l=[::1]:3300 r=62.210.198.226:56340
137+t=2026-08-19T21:27:31-0400 lvl=info msg="join connections" obj=join id=db453b8760ac l=[::1]:3300 r=62.210.198.226:50068
138+t=2026-08-19T21:27:31-0400 lvl=info msg="join connections" obj=join id=b34e608242b6 l=[::1]:3300 r=62.210.198.226:44116
139+t=2026-08-19T21:27:31-0400 lvl=info msg="join connections" obj=join id=bf12975cc54a l=[::1]:3300 r=62.210.198.226:50072
140+t=2026-08-19T21:38:02-0400 lvl=info msg="join connections" obj=join id=989be1349e22 l=[::1]:3300 r=216.73.217.52:42025
141+t=2026-08-19T21:40:19-0400 lvl=info msg="join connections" obj=join id=c2679743dfdc l=[::1]:3300 r=216.73.217.52:27053
142+t=2026-08-19T21:41:26-0400 lvl=info msg="join connections" obj=join id=9c4f11751482 l=[::1]:3300 r=216.73.217.52:55060
143+t=2026-08-19T21:41:29-0400 lvl=info msg="join connections" obj=join id=84fadf170ee4 l=[::1]:3300 r=216.73.217.52:4879
144+t=2026-08-19T21:41:29-0400 lvl=info msg="join connections" obj=join id=f09fffad840b l=[::1]:3300 r=216.73.217.52:4879
145+t=2026-08-19T21:43:25-0400 lvl=info msg="join connections" obj=join id=e37e9ac3f827 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:51950
146+t=2026-08-19T21:43:25-0400 lvl=info msg="join connections" obj=join id=049a5350fc00 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:51950
147+t=2026-08-19T21:43:25-0400 lvl=info msg="join connections" obj=join id=2f47f53d40ef l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:51952
148+t=2026-08-19T21:44:59-0400 lvl=info msg="join connections" obj=join id=0b49a3ce6c0e l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:51953
149+t=2026-08-19T21:44:59-0400 lvl=info msg="join connections" obj=join id=74aa49f6e541 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:51953
150+t=2026-08-19T21:45:00-0400 lvl=info msg="join connections" obj=join id=1cb5ad7a1381 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:51955
151+t=2026-08-19T21:45:02-0400 lvl=info msg="join connections" obj=join id=58c621506d55 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:51957
152+t=2026-08-19T21:47:58-0400 lvl=info msg="join connections" obj=join id=69544b6ba010 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:51986
153+t=2026-08-19T21:47:59-0400 lvl=info msg="join connections" obj=join id=b0d8d06e4139 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:51986
154+t=2026-08-19T21:47:59-0400 lvl=info msg="join connections" obj=join id=fbae22152165 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:51987
155+t=2026-08-19T21:47:59-0400 lvl=info msg="join connections" obj=join id=825ba5a90cf3 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:51989
156+t=2026-08-19T21:48:11-0400 lvl=info msg="join connections" obj=join id=4c535204cba4 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:51994
157+t=2026-08-19T21:48:13-0400 lvl=info msg="join connections" obj=join id=3e451ec923bf l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:51999
158+t=2026-08-19T21:48:13-0400 lvl=info msg="join connections" obj=join id=c6cf93cae865 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:51999
159+t=2026-08-19T21:48:14-0400 lvl=info msg="join connections" obj=join id=8d72a0d3b2ec l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:52001
160+t=2026-08-19T21:48:26-0400 lvl=info msg="join connections" obj=join id=0561f40a3839 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:51999
161+t=2026-08-19T21:48:36-0400 lvl=info msg="join connections" obj=join id=3ec3e709268c l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:51999
162+t=2026-08-19T21:48:45-0400 lvl=info msg="join connections" obj=join id=9e197c2031ab l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:51999
163+t=2026-08-19T21:48:45-0400 lvl=info msg="join connections" obj=join id=8b5685b5d140 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:51999
164+t=2026-08-19T21:48:45-0400 lvl=info msg="join connections" obj=join id=f2365b890332 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:52003
165+t=2026-08-19T21:48:53-0400 lvl=info msg="join connections" obj=join id=1fcd97b169b8 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:51999
166+t=2026-08-19T21:48:53-0400 lvl=info msg="join connections" obj=join id=b807fd4d185b l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:51999
167+t=2026-08-19T21:48:53-0400 lvl=info msg="join connections" obj=join id=f54674471fd0 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:52005
168+t=2026-08-19T21:48:55-0400 lvl=info msg="join connections" obj=join id=9bc293a0e30f l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:52007
169+t=2026-08-19T21:50:21-0400 lvl=info msg="join connections" obj=join id=914b31df9a61 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:52035
170+t=2026-08-19T21:50:21-0400 lvl=info msg="join connections" obj=join id=1ea4a6498aaf l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:52035
171+t=2026-08-19T21:50:21-0400 lvl=info msg="join connections" obj=join id=3abc7a449bba l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:52037
172+t=2026-08-19T21:50:23-0400 lvl=info msg="join connections" obj=join id=b4ac45e1a39c l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:52040
173+t=2026-08-19T21:50:26-0400 lvl=info msg="join connections" obj=join id=66c789ecca85 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:52043
174+t=2026-08-19T21:51:43-0400 lvl=info msg="join connections" obj=join id=4fe95d2d7042 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:52047
175+t=2026-08-19T21:52:43-0400 lvl=info msg="join connections" obj=join id=b4552c5714fa l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:52073
176+t=2026-08-19T21:53:18-0400 lvl=info msg="join connections" obj=join id=dc0e934ed2bd l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:52084
177+t=2026-08-19T21:54:12-0400 lvl=info msg="join connections" obj=join id=4aba30031d49 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:52377
178+t=2026-08-19T21:54:30-0400 lvl=info msg="join connections" obj=join id=13a47c276b60 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:52383
179+t=2026-08-19T21:54:36-0400 lvl=info msg="join connections" obj=join id=e801cbc8a0f4 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:52384
180+t=2026-08-19T21:54:36-0400 lvl=info msg="join connections" obj=join id=604bf8fadbae l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:52384
181+t=2026-08-19T21:54:36-0400 lvl=info msg="join connections" obj=join id=67ba18d9e7bb l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:52386
182+t=2026-08-19T21:54:46-0400 lvl=info msg="join connections" obj=join id=94616a930659 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:52387
183+t=2026-08-19T21:54:46-0400 lvl=info msg="join connections" obj=join id=0dfbccb8c3d6 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:52387
184+t=2026-08-19T21:54:47-0400 lvl=info msg="join connections" obj=join id=db6ce9ea5881 l=[::1]:3300 r=70.25.239.68:61380
185+t=2026-08-19T21:54:55-0400 lvl=info msg="join connections" obj=join id=bda461a22eed l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:52392
186+t=2026-08-19T21:55:35-0400 lvl=info msg="join connections" obj=join id=6417e0202d87 l=[::1]:3300 r=76.70.60.50:54151
187+t=2026-08-19T21:55:58-0400 lvl=info msg="join connections" obj=join id=9e2a734125ff l=[::1]:3300 r=76.70.60.50:54280
188+t=2026-08-19T21:56:27-0400 lvl=info msg="join connections" obj=join id=df4a75ce5c7f l=[::1]:3300 r=76.70.60.50:54412
189+t=2026-08-19T21:56:52-0400 lvl=info msg="join connections" obj=join id=199eedad2c07 l=[::1]:3300 r=76.70.60.50:54478
190+t=2026-08-19T21:57:43-0400 lvl=info msg="join connections" obj=join id=132eb0da7cfc l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:52404
191+t=2026-08-19T21:57:46-0400 lvl=info msg="join connections" obj=join id=837528564b9f l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:52406
192+t=2026-08-19T21:57:46-0400 lvl=info msg="join connections" obj=join id=5826ebba1769 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:52406
193+t=2026-08-19T21:57:46-0400 lvl=info msg="join connections" obj=join id=ac722a7a1f87 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:52407
194+t=2026-08-19T21:57:46-0400 lvl=info msg="join connections" obj=join id=225ca92b4854 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:52409
195+t=2026-08-19T21:58:06-0400 lvl=info msg="join connections" obj=join id=567ac0f902fb l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:52406
196+t=2026-08-19T21:58:10-0400 lvl=info msg="join connections" obj=join id=28d839db5411 l=[::1]:3300 r=76.70.60.50:54850
197+t=2026-08-19T21:58:35-0400 lvl=info msg="join connections" obj=join id=56e6de71eb26 l=[::1]:3300 r=76.70.60.50:54915
198+t=2026-08-19T21:58:59-0400 lvl=info msg="join connections" obj=join id=da34b55080fa l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:52423
199+t=2026-08-19T21:59:00-0400 lvl=info msg="join connections" obj=join id=b7736ce4f9d2 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:52426
200+t=2026-08-19T22:00:23-0400 lvl=info msg="join connections" obj=join id=885fbf944200 l=[::1]:3300 r=70.25.239.68:61387
201+t=2026-08-19T22:00:25-0400 lvl=info msg="join connections" obj=join id=4a0cb0b6b8d9 l=[::1]:3300 r=76.70.60.50:55389
202+t=2026-08-19T22:00:31-0400 lvl=info msg="join connections" obj=join id=cfc9a7485d7a l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:52436
203+t=2026-08-19T22:00:32-0400 lvl=info msg="join connections" obj=join id=32c84474834e l=[::1]:3300 r=70.25.239.68:63336
204+t=2026-08-19T22:00:41-0400 lvl=info msg="join connections" obj=join id=584ea3eba612 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:52441
205+t=2026-08-19T22:00:48-0400 lvl=info msg="join connections" obj=join id=1e4aa6df079d l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:52443
206+t=2026-08-19T22:00:53-0400 lvl=info msg="join connections" obj=join id=1e43c5248adb l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:52447
207+t=2026-08-19T22:02:50-0400 lvl=info msg="join connections" obj=join id=483f92c2c0e2 l=[::1]:3300 r=70.25.239.68:63392
208+t=2026-08-19T22:04:05-0400 lvl=info msg="join connections" obj=join id=6a1cf6f5c1f9 l=[::1]:3300 r=70.25.239.68:63430
209+t=2026-08-19T22:04:06-0400 lvl=info msg="join connections" obj=join id=ee3a56157880 l=[::1]:3300 r=70.25.239.68:63439
210+t=2026-08-19T22:04:33-0400 lvl=info msg="join connections" obj=join id=190558b97605 l=[::1]:3300 r=70.25.239.68:63454
211+t=2026-08-19T22:04:33-0400 lvl=info msg="join connections" obj=join id=ac0228440018 l=[::1]:3300 r=70.25.239.68:63455
212+t=2026-08-19T22:04:33-0400 lvl=info msg="join connections" obj=join id=5f31718130e2 l=[::1]:3300 r=70.25.239.68:63456
213+t=2026-08-19T22:04:33-0400 lvl=info msg="join connections" obj=join id=4373318ebd36 l=[::1]:3300 r=70.25.239.68:63457
214+t=2026-08-19T22:04:34-0400 lvl=info msg="join connections" obj=join id=bf29ac1c79dc l=[::1]:3300 r=70.25.239.68:63458
215+t=2026-08-19T22:04:34-0400 lvl=info msg="join connections" obj=join id=13a60f98b172 l=[::1]:3300 r=70.25.239.68:63459
216+t=2026-08-19T22:04:34-0400 lvl=info msg="join connections" obj=join id=2a934ff11959 l=[::1]:3300 r=70.25.239.68:63460
217+t=2026-08-19T22:04:34-0400 lvl=info msg="join connections" obj=join id=e53564ead02b l=[::1]:3300 r=70.25.239.68:63461
218+t=2026-08-19T22:04:35-0400 lvl=info msg="join connections" obj=join id=381591839ed1 l=[::1]:3300 r=70.25.239.68:63462
219+t=2026-08-19T22:04:35-0400 lvl=info msg="join connections" obj=join id=7d4626114a07 l=[::1]:3300 r=70.25.239.68:63463
220+t=2026-08-19T22:04:35-0400 lvl=info msg="join connections" obj=join id=65da02325afa l=[::1]:3300 r=70.25.239.68:63464
221+t=2026-08-19T22:04:35-0400 lvl=info msg="join connections" obj=join id=9b1bf7b0cd54 l=[::1]:3300 r=70.25.239.68:63465
222+t=2026-08-19T22:04:35-0400 lvl=info msg="join connections" obj=join id=b134cab4d853 l=[::1]:3300 r=70.25.239.68:63466
223+t=2026-08-19T22:04:35-0400 lvl=info msg="join connections" obj=join id=c255f283eb1b l=[::1]:3300 r=70.25.239.68:63467
224+t=2026-08-19T22:04:36-0400 lvl=info msg="join connections" obj=join id=c74aa187453a l=[::1]:3300 r=70.25.239.68:63468
225+t=2026-08-19T22:04:36-0400 lvl=info msg="join connections" obj=join id=fc0b38050874 l=[::1]:3300 r=70.25.239.68:63469
226+t=2026-08-19T22:08:34-0400 lvl=info msg="join connections" obj=join id=bda40b869978 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:52502
227+t=2026-08-19T22:08:42-0400 lvl=info msg="join connections" obj=join id=dc767205f0d3 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:52504
228+t=2026-08-19T22:09:38-0400 lvl=info msg="join connections" obj=join id=07d704a82bdc l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:52513
229+t=2026-08-19T22:09:49-0400 lvl=info msg="join connections" obj=join id=c0f4019ad697 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:52515
230+t=2026-08-19T22:12:33-0400 lvl=info msg="join connections" obj=join id=5e5c5347cc91 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:52537
231+t=2026-08-19T22:12:34-0400 lvl=info msg="join connections" obj=join id=cf09795ece3f l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:52540
232+t=2026-08-19T22:13:00-0400 lvl=info msg="join connections" obj=join id=bed5aaa493f2 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:52545
233+t=2026-08-19T22:13:16-0400 lvl=info msg="join connections" obj=join id=b5e2f2f6569d l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:52549
234+t=2026-08-19T22:13:16-0400 lvl=info msg="join connections" obj=join id=9e15e747c50b l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:52549
235+t=2026-08-19T22:13:20-0400 lvl=info msg="join connections" obj=join id=d368faf8cfef l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:52553
236+t=2026-08-19T22:21:47-0400 lvl=info msg="join connections" obj=join id=20c785244377 l=[::1]:3300 r=[2001:bc8:701:51:da5e:d3ff:feea:e65d]:47378
237+t=2026-08-19T22:21:51-0400 lvl=info msg="join connections" obj=join id=8d2900b01396 l=[::1]:3300 r=[2001:bc8:701:51:da5e:d3ff:feea:e65d]:46243
238+t=2026-08-19T22:21:51-0400 lvl=info msg="join connections" obj=join id=6c434aeb57f4 l=[::1]:3300 r=[2001:bc8:701:51:da5e:d3ff:feea:e65d]:46243
239+t=2026-08-19T22:21:51-0400 lvl=info msg="join connections" obj=join id=8a5f3d955e63 l=[::1]:3300 r=[2001:bc8:701:51:da5e:d3ff:feea:e65d]:46243
240+t=2026-08-19T22:21:51-0400 lvl=info msg="join connections" obj=join id=ef93e21c210e l=[::1]:3300 r=[2001:bc8:701:51:da5e:d3ff:feea:e65d]:46243
241+t=2026-08-19T22:21:51-0400 lvl=info msg="join connections" obj=join id=9df67c3643d9 l=[::1]:3300 r=[2001:bc8:701:51:da5e:d3ff:feea:e65d]:46243
242+t=2026-08-19T22:21:51-0400 lvl=info msg="join connections" obj=join id=9cc13103861e l=[::1]:3300 r=[2001:bc8:701:51:da5e:d3ff:feea:e65d]:46276
243+t=2026-08-19T22:21:51-0400 lvl=info msg="join connections" obj=join id=5aed8f8cf0f5 l=[::1]:3300 r=[2001:bc8:701:51:da5e:d3ff:feea:e65d]:46276
244+t=2026-08-19T22:21:51-0400 lvl=info msg="join connections" obj=join id=f1b2b0bc10a6 l=[::1]:3300 r=[2001:bc8:701:51:da5e:d3ff:feea:e65d]:46276
245+t=2026-08-19T22:21:51-0400 lvl=info msg="join connections" obj=join id=4895672234ff l=[::1]:3300 r=[2001:bc8:701:51:da5e:d3ff:feea:e65d]:46276
246+t=2026-08-19T22:21:51-0400 lvl=info msg="join connections" obj=join id=ab8d1e9a8013 l=[::1]:3300 r=[2001:bc8:701:51:da5e:d3ff:feea:e65d]:46276
247+t=2026-08-19T22:21:57-0400 lvl=info msg="join connections" obj=join id=4a6d53caa3d4 l=[::1]:3300 r=[2001:bc8:701:51:da5e:d3ff:feea:e65d]:51356
248+t=2026-08-19T22:21:58-0400 lvl=info msg="join connections" obj=join id=6a7cb4e462dd l=[::1]:3300 r=[2001:bc8:701:51:da5e:d3ff:feea:e65d]:39912
249+t=2026-08-19T22:21:58-0400 lvl=info msg="join connections" obj=join id=a34eb4eabeab l=[::1]:3300 r=[2001:bc8:701:51:da5e:d3ff:feea:e65d]:34354
250+t=2026-08-19T22:21:58-0400 lvl=info msg="join connections" obj=join id=bbd51c5969d7 l=[::1]:3300 r=[2001:bc8:701:51:da5e:d3ff:feea:e65d]:51362
251+t=2026-08-19T22:22:12-0400 lvl=info msg="join connections" obj=join id=6bc36f78ee80 l=[::1]:3300 r=[2001:bc8:701:51:da5e:d3ff:fe49:a574]:60456
252+t=2026-08-19T22:22:14-0400 lvl=info msg="join connections" obj=join id=f5b96abcd83f l=[::1]:3300 r=[2001:bc8:701:51:da5e:d3ff:fe49:a574]:36231
253+t=2026-08-19T22:22:14-0400 lvl=info msg="join connections" obj=join id=9de387db4a29 l=[::1]:3300 r=[2001:bc8:701:51:da5e:d3ff:fe49:a574]:33566
254+t=2026-08-19T22:22:14-0400 lvl=info msg="join connections" obj=join id=112e3b0df8ed l=[::1]:3300 r=[2001:bc8:701:51:da5e:d3ff:fe49:a574]:36231
255+t=2026-08-19T22:22:14-0400 lvl=info msg="join connections" obj=join id=374dc8f030cd l=[::1]:3300 r=[2001:bc8:701:51:da5e:d3ff:fe49:a574]:36231
256+t=2026-08-19T22:22:14-0400 lvl=info msg="join connections" obj=join id=7efb9e81ae6e l=[::1]:3300 r=[2001:bc8:701:51:da5e:d3ff:fe49:a574]:36231
257+t=2026-08-19T22:22:14-0400 lvl=info msg="join connections" obj=join id=28eaf499ffbe l=[::1]:3300 r=[2001:bc8:701:51:da5e:d3ff:fe49:a574]:36231
258+t=2026-08-19T22:22:14-0400 lvl=info msg="join connections" obj=join id=1a83132fafe1 l=[::1]:3300 r=[2001:bc8:701:51:da5e:d3ff:fe49:a574]:33566
259+t=2026-08-19T22:22:14-0400 lvl=info msg="join connections" obj=join id=1b0d57125f3e l=[::1]:3300 r=[2001:bc8:701:51:da5e:d3ff:fe49:a574]:33566
260+t=2026-08-19T22:22:14-0400 lvl=info msg="join connections" obj=join id=ffb381b9e1ed l=[::1]:3300 r=[2001:bc8:701:51:da5e:d3ff:fe49:a574]:33566
261+t=2026-08-19T22:22:14-0400 lvl=info msg="join connections" obj=join id=5dc0b6685362 l=[::1]:3300 r=[2001:bc8:701:51:da5e:d3ff:fe49:a574]:33566
262+t=2026-08-19T22:22:19-0400 lvl=info msg="join connections" obj=join id=49f169e29d78 l=[::1]:3300 r=[2001:bc8:701:51:da5e:d3ff:fe49:a574]:33578
263+t=2026-08-19T22:22:30-0400 lvl=info msg="join connections" obj=join id=6c2ef35c118e l=[::1]:3300 r=[2001:bc8:701:51:da5e:d3ff:fe49:a574]:36720
264+t=2026-08-19T22:22:30-0400 lvl=info msg="join connections" obj=join id=f68d59a5433b l=[::1]:3300 r=[2001:bc8:701:51:da5e:d3ff:fe49:a574]:47560
265+t=2026-08-19T22:22:30-0400 lvl=info msg="join connections" obj=join id=5125086bba58 l=[::1]:3300 r=[2001:bc8:701:51:da5e:d3ff:fe49:a574]:45360
266+t=2026-08-19T22:27:24-0400 lvl=info msg="join connections" obj=join id=d51f258e903b l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53033
267+t=2026-08-19T22:31:12-0400 lvl=info msg="join connections" obj=join id=726cff0fc2b4 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53144
268+t=2026-08-19T22:32:18-0400 lvl=info msg="join connections" obj=join id=6d06cf756852 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53237
269+t=2026-08-19T22:32:19-0400 lvl=info msg="join connections" obj=join id=433871de66bd l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53237
270+t=2026-08-19T22:32:19-0400 lvl=info msg="join connections" obj=join id=c462a4209aff l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53238
271+t=2026-08-19T22:32:19-0400 lvl=info msg="join connections" obj=join id=0b0d34cc534c l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53240
272+t=2026-08-19T22:32:21-0400 lvl=info msg="join connections" obj=join id=945e649fbe3b l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53245
273+t=2026-08-19T22:33:39-0400 lvl=info msg="join connections" obj=join id=397819b2dda0 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53250
274+t=2026-08-19T22:33:41-0400 lvl=info msg="join connections" obj=join id=b3664f4650a8 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53253
275+t=2026-08-19T22:35:57-0400 lvl=info msg="join connections" obj=join id=9f2228e1e020 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53261
276+t=2026-08-19T22:36:02-0400 lvl=info msg="join connections" obj=join id=15d98ddf375c l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53263
277+t=2026-08-19T22:36:11-0400 lvl=info msg="join connections" obj=join id=3fef013ea81d l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53263
278+t=2026-08-19T22:36:29-0400 lvl=info msg="join connections" obj=join id=ce61870e5f6c l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53263
279+t=2026-08-19T22:54:50-0400 lvl=info msg="join connections" obj=join id=65373a9dccbd l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53337
280+t=2026-08-19T22:54:50-0400 lvl=info msg="join connections" obj=join id=aa97c7ee2835 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53337
281+t=2026-08-19T22:54:50-0400 lvl=info msg="join connections" obj=join id=7d3e834533a0 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53339
282+t=2026-08-19T23:00:10-0400 lvl=info msg="join connections" obj=join id=d26143d16bef l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53379
283+t=2026-08-19T23:00:10-0400 lvl=info msg="join connections" obj=join id=455af43b0e28 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53380
284+t=2026-08-19T23:00:10-0400 lvl=info msg="join connections" obj=join id=0fef13e0d4cb l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53380
285+t=2026-08-19T23:00:10-0400 lvl=info msg="join connections" obj=join id=df9ecd519d2c l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53383
286+t=2026-08-19T23:05:54-0400 lvl=info msg="join connections" obj=join id=c38949d258c7 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53416
287+t=2026-08-19T23:06:12-0400 lvl=info msg="join connections" obj=join id=74b84426409f l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53418
288+t=2026-08-19T23:07:38-0400 lvl=info msg="join connections" obj=join id=dda8a89c4b42 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53427
289+t=2026-08-19T23:07:39-0400 lvl=info msg="join connections" obj=join id=b52434469f58 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53430
290+t=2026-08-19T23:25:58-0400 lvl=info msg="join connections" obj=join id=612f510852e3 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53543
291+t=2026-08-19T23:25:59-0400 lvl=info msg="join connections" obj=join id=60e1852d7e19 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53546
292+t=2026-08-19T23:48:37-0400 lvl=info msg="join connections" obj=join id=9e14c1d18f72 l=[::1]:3300 r=46.232.235.133:7264
293+t=2026-08-19T23:48:37-0400 lvl=info msg="join connections" obj=join id=f52a812c1b4f l=[::1]:3300 r=46.232.235.133:7280
294+t=2026-08-19T23:48:37-0400 lvl=info msg="join connections" obj=join id=fd0fa28f0e3a l=[::1]:3300 r=46.232.235.133:7294
295+t=2026-08-19T23:48:38-0400 lvl=info msg="join connections" obj=join id=db53824ec136 l=[::1]:3300 r=46.232.235.133:20336
296+t=2026-08-19T23:48:38-0400 lvl=info msg="join connections" obj=join id=9ad84d1bc1e1 l=[::1]:3300 r=46.232.235.133:58660
297+t=2026-08-19T23:48:38-0400 lvl=info msg="join connections" obj=join id=af3ac03b5984 l=[::1]:3300 r=46.232.235.133:58666
298+t=2026-08-20T00:15:41-0400 lvl=info msg="join connections" obj=join id=1b8f0d107d32 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53885
299+t=2026-08-20T00:15:41-0400 lvl=info msg="join connections" obj=join id=c1dce6c247ee l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53886
300+t=2026-08-20T00:15:41-0400 lvl=info msg="join connections" obj=join id=c0368d030769 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53886
301+t=2026-08-20T00:15:41-0400 lvl=info msg="join connections" obj=join id=a9e6335a3636 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53891
302+t=2026-08-20T00:19:13-0400 lvl=info msg="join connections" obj=join id=a781d17689fe l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53909
303+t=2026-08-20T00:19:57-0400 lvl=info msg="join connections" obj=join id=83f279ccd37f l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53922
304+t=2026-08-20T00:20:23-0400 lvl=info msg="join connections" obj=join id=3b9c89253542 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53924
305+t=2026-08-20T00:22:21-0400 lvl=info msg="join connections" obj=join id=d556db1553ac l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53957
306+t=2026-08-20T00:22:21-0400 lvl=info msg="join connections" obj=join id=3bbcb0a5454a l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53957
307+t=2026-08-20T00:22:21-0400 lvl=info msg="join connections" obj=join id=ad28a02f3aa3 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53959
308+t=2026-08-20T00:23:16-0400 lvl=info msg="join connections" obj=join id=b505cc4fc218 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53964
309+t=2026-08-20T00:24:34-0400 lvl=info msg="join connections" obj=join id=e04c1591949d l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53968
310+t=2026-08-20T00:24:39-0400 lvl=info msg="join connections" obj=join id=3eea74dd9688 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53970
311+t=2026-08-20T00:24:47-0400 lvl=info msg="join connections" obj=join id=dfd40879566c l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53970
312+t=2026-08-20T00:24:57-0400 lvl=info msg="join connections" obj=join id=8dbd2456f840 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53970
313+t=2026-08-20T00:24:57-0400 lvl=info msg="join connections" obj=join id=108b8cc3e104 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53970
314+t=2026-08-20T00:24:57-0400 lvl=info msg="join connections" obj=join id=aad32ee538ae l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53970
315+t=2026-08-20T00:24:57-0400 lvl=info msg="join connections" obj=join id=3a1991e355bf l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53970
316+t=2026-08-20T00:24:57-0400 lvl=info msg="join connections" obj=join id=df32ca24efb0 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:53970
317+t=2026-08-20T00:24:57-0400 lvl=info msg="join connections" obj=join id=0e521e95b109 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:54059
318+t=2026-08-20T00:25:03-0400 lvl=info msg="join connections" obj=join id=f2a00f734278 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:54060
319+t=2026-08-20T00:25:03-0400 lvl=info msg="join connections" obj=join id=28aa5e958664 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:54061
320+t=2026-08-20T00:25:03-0400 lvl=info msg="join connections" obj=join id=3fd131907557 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:54061
321+t=2026-08-20T00:25:03-0400 lvl=info msg="join connections" obj=join id=3412aa770323 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:54061
322+t=2026-08-20T00:38:11-0400 lvl=info msg="join connections" obj=join id=83adadeccbc3 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:54342
323+t=2026-08-20T00:38:39-0400 lvl=info msg="join connections" obj=join id=f7755b441375 l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:54373
324+t=2026-08-20T00:38:39-0400 lvl=info msg="join connections" obj=join id=274ae66881de l=[::1]:3300 r=[2605:b100:121:7aaf:a44c:a261:eb80:fba]:54376
325+t=2026-08-20T01:02:03-0400 lvl=info msg="join connections" obj=join id=504deb98fb4c l=[::1]:3300 r=70.25.239.68:61599
added data/sessions.json +1 −0
@@ -0,0 +1 @@
1+{"d08eba390f7e302448b3ad0904841b180b7a97c4be547185d6b383f341f5b651":{"created":1787184586590,"last":1787184586861},"bf96e101ba362b5964767484aaf148081bf85dbaefafb6396a346223f3f4bbfc":{"created":1787184858159,"last":1787191223674},"1729725f9065ea67c047e062f2dce440e44660763199c5cd81f614c1bb669069":{"created":1787185142512,"last":1787185142512},"58389ecc05a5ef3d63f28c27d46026a1184e275de3ddc9ae375dfc7f6564e191":{"created":1787185142681,"last":1787191476301},"3dffbd143a2cc043fde94e4a5b9c93a395f09d814797c04cabd1be8832d2e062":{"created":1787185194996,"last":1787199741938}}
\ No newline at end of file
added data/transcripts/21d6c1690bd84a05.jsonl +8 −0
@@ -0,0 +1,8 @@
1+{"type":"user_prompt","text":"Allo","ts":1787199418219}
2+{"type":"status","state":"running"}
3+{"type":"claude","event":{"type":"system","subtype":"init","cwd":"/Users/simon-pierreboucher/apps/crea-ka","session_id":"1a808aed-e9c3-4913-bef8-698d375e8789","tools":["Task","AskUserQuestion","Bash","CronCreate","CronDelete","CronList","Edit","EnterPlanMode","EnterWorktree","ExitPlanMode","ExitWorktree","Glob","Grep","Monitor","NotebookEdit","PushNotification","Read","RemoteTrigger","ScheduleWakeup","Skill","TaskOutput","TaskStop","TodoWrite","ToolSearch","WebFetch","WebSearch","Write"],"mcp_servers":[{"name":"adminka","status":"connected"}],"model":"claude-fable-5","permissionMode":"default","slash_commands":["update-config","debug","simplify","batch","fewer-permission-prompts","loop","schedule","claude-api","clear","compact","context","cost","heapdump","init","review","security-review","insights","team-onboarding"],"apiKeySource":"ANTHROPIC_API_KEY","claude_code_version":"2.1.117","output_style":"default","agents":["Explore","general-purpose","Plan","statusline-setup"],"skills":["update-config","debug","simplify","batch","fewer-permission-prompts","loop","schedule","claude-api"],"plugins":[],"uuid":"b6371561-ada7-4736-b07c-7b339cef27d3","memory_paths":{"auto":"/Users/simon-pierreboucher/.claude/projects/-Users-simon-pierreboucher-apps-crea-ka/memory/"},"fast_mode_state":"off"}}
4+{"type":"claude","event":{"type":"system","subtype":"status","status":"requesting","uuid":"5033ddbf-fdac-42fd-a18c-31ad87c78c4c","session_id":"1a808aed-e9c3-4913-bef8-698d375e8789"}}
5+{"type":"claude","event":{"type":"assistant","message":{"model":"claude-fable-5","id":"msg_011CeDMWHgBmF1HqDGXubBtY","type":"message","role":"assistant","content":[{"type":"thinking","thinking":"","signature":"CAIS3gIKpAEIEBgCKkC316Sy+OTuBVYoIgZuUsMrkEVoa7m9pMW1lNwVODFFdod5/ftcpvPEqsCL8FVYp9gBbIpKVoQv+R1IPV/XOzx5Mg5jbGF1ZGUtZmFibGUtNTgBQgh0aGlua2luZ1okNmZjYzhmODMtMWY5Yy00ZDMzLWJhMDctNGQ0ZGYzN2Q2N2Y1chD0eFf7D17nbHkCPBxNVtIaiAEBqAHA/5nUBhIMqQ1Wc1+Fi07SJqJPGgweovy1bvKmD82eK4kiMCls4n81u7qJv7VenCk7jjVpqwOuXKGKPgGJIkHOZBKD5TowDl6I/OOrgUcz9YmepCpngnb/GcFbt+wvRpxTEzn+1XQhTPEY0A/6FUJ3JZT3+G+byJpqUktUocjsPEsHzUKLIxEaGLUzUNPOdzloQDeVK41Gsny4hXrdGlCKuTYWss/rmacTS5LqawikGziOBbkasMoGb/auaxgB"}],"stop_reason":null,"stop_sequence":null,"stop_details":null,"usage":{"input_tokens":2,"cache_creation_input_tokens":39715,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":39715,"ephemeral_1h_input_tokens":0},"output_tokens":2,"service_tier":"standard","inference_geo":"global"},"context_management":null},"parent_tool_use_id":null,"session_id":"1a808aed-e9c3-4913-bef8-698d375e8789","uuid":"16e03e27-d007-4bab-987e-b27f34c9adb9"}}
6+{"type":"claude","event":{"type":"assistant","message":{"model":"claude-fable-5","id":"msg_011CeDMWHgBmF1HqDGXubBtY","type":"message","role":"assistant","content":[{"type":"text","text":"Allo ! Je suis sur M3U96b, dans le repo **crea-ka** (`~/apps/crea-ka`). Qu'est-ce que je peux faire pour toi ?"}],"stop_reason":null,"stop_sequence":null,"stop_details":null,"usage":{"input_tokens":2,"cache_creation_input_tokens":39715,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":39715,"ephemeral_1h_input_tokens":0},"output_tokens":2,"service_tier":"standard","inference_geo":"global"},"context_management":null},"parent_tool_use_id":null,"session_id":"1a808aed-e9c3-4913-bef8-698d375e8789","uuid":"9e733460-f754-49d5-b4bf-04ab1d28c2fe"}}
7+{"type":"claude","event":{"type":"result","subtype":"success","is_error":false,"api_error_status":null,"duration_ms":6960,"duration_api_ms":6935,"num_turns":1,"result":"Allo ! Je suis sur M3U96b, dans le repo **crea-ka** (`~/apps/crea-ka`). Qu'est-ce que je peux faire pour toi ?","stop_reason":"end_turn","session_id":"1a808aed-e9c3-4913-bef8-698d375e8789","total_cost_usd":0.15040725000000002,"usage":{"input_tokens":2,"cache_creation_input_tokens":39715,"cache_read_input_tokens":0,"output_tokens":98,"server_tool_use":{"web_search_requests":0,"web_fetch_requests":0},"service_tier":"standard","cache_creation":{"ephemeral_1h_input_tokens":0,"ephemeral_5m_input_tokens":39715},"inference_geo":"","iterations":[{"input_tokens":2,"output_tokens":98,"cache_read_input_tokens":0,"cache_creation_input_tokens":39715,"cache_creation":{"ephemeral_5m_input_tokens":39715,"ephemeral_1h_input_tokens":0},"type":"message"}],"speed":"standard"},"modelUsage":{"claude-fable-5":{"inputTokens":2,"outputTokens":98,"cacheReadInputTokens":0,"cacheCreationInputTokens":39715,"webSearchRequests":0,"costUSD":0.15040725000000002,"contextWindow":200000,"maxOutputTokens":32000}},"permission_denials":[],"terminal_reason":"completed","fast_mode_state":"off","uuid":"029e0311-11f4-4729-a3a1-6022a5eff3c2"}}
8+{"type":"status","state":"idle"}
added node_modules/.package-lock.json +29 −0
@@ -0,0 +1,29 @@
1+{
2+ "name": "admin-ka",
3+ "version": "1.0.0",
4+ "lockfileVersion": 3,
5+ "requires": true,
6+ "packages": {
7+ "node_modules/ws": {
8+ "version": "8.21.3",
9+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.3.tgz",
10+ "integrity": "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==",
11+ "license": "MIT",
12+ "engines": {
13+ "node": ">=10.0.0"
14+ },
15+ "peerDependencies": {
16+ "bufferutil": "^4.0.1",
17+ "utf-8-validate": ">=5.0.2"
18+ },
19+ "peerDependenciesMeta": {
20+ "bufferutil": {
21+ "optional": true
22+ },
23+ "utf-8-validate": {
24+ "optional": true
25+ }
26+ }
27+ }
28+ }
29+}
added node_modules/ws/LICENSE +20 −0
@@ -0,0 +1,20 @@
1+Copyright (c) 2011 Einar Otto Stangvik <einaros@gmail.com>
2+Copyright (c) 2013 Arnout Kazemier and contributors
3+Copyright (c) 2016 Luigi Pinca and contributors
4+
5+Permission is hereby granted, free of charge, to any person obtaining a copy of
6+this software and associated documentation files (the "Software"), to deal in
7+the Software without restriction, including without limitation the rights to
8+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9+the Software, and to permit persons to whom the Software is furnished to do so,
10+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, FITNESS
17+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
added node_modules/ws/README.md +548 −0
@@ -0,0 +1,548 @@
1+# ws: a Node.js WebSocket library
2+
3+[![Version npm](https://img.shields.io/npm/v/ws.svg?logo=npm)](https://www.npmjs.com/package/ws)
4+[![CI](https://img.shields.io/github/actions/workflow/status/websockets/ws/ci.yml?branch=master&label=CI&logo=github)](https://github.com/websockets/ws/actions?query=workflow%3ACI+branch%3Amaster)
5+[![Coverage Status](https://img.shields.io/coveralls/websockets/ws/master.svg?logo=coveralls)](https://coveralls.io/github/websockets/ws)
6+
7+ws is a simple to use, blazing fast, and thoroughly tested WebSocket client and
8+server implementation.
9+
10+Passes the quite extensive Autobahn test suite: [server][server-report],
11+[client][client-report].
12+
13+**Note**: This module does not work in the browser. The client in the docs is a
14+reference to a backend with the role of a client in the WebSocket communication.
15+Browser clients must use the native
16+[`WebSocket`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket)
17+object. To make the same code work seamlessly on Node.js and the browser, you
18+can use one of the many wrappers available on npm, like
19+[isomorphic-ws](https://github.com/heineiuo/isomorphic-ws).
20+
21+## Table of Contents
22+
23+- [Protocol support](#protocol-support)
24+- [Installing](#installing)
25+ - [Opt-in for performance](#opt-in-for-performance)
26+ - [Legacy opt-in for performance](#legacy-opt-in-for-performance)
27+- [API docs](#api-docs)
28+- [WebSocket compression](#websocket-compression)
29+- [Usage examples](#usage-examples)
30+ - [Sending and receiving text data](#sending-and-receiving-text-data)
31+ - [Sending binary data](#sending-binary-data)
32+ - [Simple server](#simple-server)
33+ - [External HTTP/S server](#external-https-server)
34+ - [Multiple servers sharing a single HTTP/S server](#multiple-servers-sharing-a-single-https-server)
35+ - [Client authentication](#client-authentication)
36+ - [Server broadcast](#server-broadcast)
37+ - [Round-trip time](#round-trip-time)
38+ - [Use the Node.js streams API](#use-the-nodejs-streams-api)
39+ - [Other examples](#other-examples)
40+- [FAQ](#faq)
41+ - [How to get the IP address of the client?](#how-to-get-the-ip-address-of-the-client)
42+ - [How to detect and close broken connections?](#how-to-detect-and-close-broken-connections)
43+ - [How to connect via a proxy?](#how-to-connect-via-a-proxy)
44+- [Changelog](#changelog)
45+- [License](#license)
46+
47+## Protocol support
48+
49+- **HyBi drafts 07-12** (Use the option `protocolVersion: 8`)
50+- **HyBi drafts 13-17** (Current default, alternatively option
51+ `protocolVersion: 13`)
52+
53+## Installing
54+
55+```
56+npm install ws
57+```
58+
59+### Opt-in for performance
60+
61+[bufferutil][] is an optional module that can be installed alongside the ws
62+module:
63+
64+```
65+npm install --save-optional bufferutil
66+```
67+
68+This is a binary addon that improves the performance of certain operations such
69+as masking and unmasking the data payload of the WebSocket frames. Prebuilt
70+binaries are available for the most popular platforms, so you don't necessarily
71+need to have a C++ compiler installed on your machine.
72+
73+To force ws to not use bufferutil, use the
74+[`WS_NO_BUFFER_UTIL`](./doc/ws.md#ws_no_buffer_util) environment variable. This
75+can be useful to enhance security in systems where a user can put a package in
76+the package search path of an application of another user, due to how the
77+Node.js resolver algorithm works.
78+
79+#### Legacy opt-in for performance
80+
81+If you are running on an old version of Node.js (prior to v18.14.0), ws also
82+supports the [utf-8-validate][] module:
83+
84+```
85+npm install --save-optional utf-8-validate
86+```
87+
88+This contains a binary polyfill for [`buffer.isUtf8()`][].
89+
90+To force ws not to use utf-8-validate, use the
91+[`WS_NO_UTF_8_VALIDATE`](./doc/ws.md#ws_no_utf_8_validate) environment variable.
92+
93+## API docs
94+
95+See [`/doc/ws.md`](./doc/ws.md) for Node.js-like documentation of ws classes and
96+utility functions.
97+
98+## WebSocket compression
99+
100+ws supports the [permessage-deflate extension][permessage-deflate] which enables
101+the client and server to negotiate a compression algorithm and its parameters,
102+and then selectively apply it to the data payloads of each WebSocket message.
103+
104+The extension is disabled by default on the server and enabled by default on the
105+client. It adds a significant overhead in terms of performance and memory
106+consumption so we suggest to enable it only if it is really needed.
107+
108+Note that Node.js has a variety of issues with high-performance compression,
109+where increased concurrency, especially on Linux, can lead to [catastrophic
110+memory fragmentation][node-zlib-bug] and slow performance. If you intend to use
111+permessage-deflate in production, it is worthwhile to set up a test
112+representative of your workload and ensure Node.js/zlib will handle it with
113+acceptable performance and memory usage.
114+
115+Tuning of permessage-deflate can be done via the options defined below. You can
116+also use `zlibDeflateOptions` and `zlibInflateOptions`, which is passed directly
117+into the creation of [raw deflate/inflate streams][node-zlib-deflaterawdocs].
118+
119+See [the docs][ws-server-options] for more options.
120+
121+```js
122+import WebSocket, { WebSocketServer } from 'ws';
123+
124+const wss = new WebSocketServer({
125+ port: 8080,
126+ perMessageDeflate: {
127+ zlibDeflateOptions: {
128+ // See zlib defaults.
129+ chunkSize: 1024,
130+ memLevel: 7,
131+ level: 3
132+ },
133+ zlibInflateOptions: {
134+ chunkSize: 10 * 1024
135+ },
136+ // Other options settable:
137+ clientNoContextTakeover: true, // Defaults to negotiated value.
138+ serverNoContextTakeover: true, // Defaults to negotiated value.
139+ serverMaxWindowBits: 10, // Defaults to negotiated value.
140+ // Below options specified as default values.
141+ concurrencyLimit: 10, // Limits zlib concurrency for perf.
142+ threshold: 1024 // Size (in bytes) below which messages
143+ // should not be compressed if context takeover is disabled.
144+ }
145+});
146+```
147+
148+The client will only use the extension if it is supported and enabled on the
149+server. To always disable the extension on the client, set the
150+`perMessageDeflate` option to `false`.
151+
152+```js
153+import WebSocket from 'ws';
154+
155+const ws = new WebSocket('ws://www.host.com/path', {
156+ perMessageDeflate: false
157+});
158+```
159+
160+## Usage examples
161+
162+### Sending and receiving text data
163+
164+```js
165+import WebSocket from 'ws';
166+
167+const ws = new WebSocket('ws://www.host.com/path');
168+
169+ws.on('error', console.error);
170+
171+ws.on('open', function open() {
172+ ws.send('something');
173+});
174+
175+ws.on('message', function message(data) {
176+ console.log('received: %s', data);
177+});
178+```
179+
180+### Sending binary data
181+
182+```js
183+import WebSocket from 'ws';
184+
185+const ws = new WebSocket('ws://www.host.com/path');
186+
187+ws.on('error', console.error);
188+
189+ws.on('open', function open() {
190+ const array = new Float32Array(5);
191+
192+ for (var i = 0; i < array.length; ++i) {
193+ array[i] = i / 2;
194+ }
195+
196+ ws.send(array);
197+});
198+```
199+
200+### Simple server
201+
202+```js
203+import { WebSocketServer } from 'ws';
204+
205+const wss = new WebSocketServer({ port: 8080 });
206+
207+wss.on('connection', function connection(ws) {
208+ ws.on('error', console.error);
209+
210+ ws.on('message', function message(data) {
211+ console.log('received: %s', data);
212+ });
213+
214+ ws.send('something');
215+});
216+```
217+
218+### External HTTP/S server
219+
220+```js
221+import { createServer } from 'https';
222+import { readFileSync } from 'fs';
223+import { WebSocketServer } from 'ws';
224+
225+const server = createServer({
226+ cert: readFileSync('/path/to/cert.pem'),
227+ key: readFileSync('/path/to/key.pem')
228+});
229+const wss = new WebSocketServer({ server });
230+
231+wss.on('connection', function connection(ws) {
232+ ws.on('error', console.error);
233+
234+ ws.on('message', function message(data) {
235+ console.log('received: %s', data);
236+ });
237+
238+ ws.send('something');
239+});
240+
241+server.listen(8080);
242+```
243+
244+### Multiple servers sharing a single HTTP/S server
245+
246+```js
247+import { createServer } from 'http';
248+import { WebSocketServer } from 'ws';
249+
250+const server = createServer();
251+const wss1 = new WebSocketServer({ noServer: true });
252+const wss2 = new WebSocketServer({ noServer: true });
253+
254+wss1.on('connection', function connection(ws) {
255+ ws.on('error', console.error);
256+
257+ // ...
258+});
259+
260+wss2.on('connection', function connection(ws) {
261+ ws.on('error', console.error);
262+
263+ // ...
264+});
265+
266+server.on('upgrade', function upgrade(request, socket, head) {
267+ const { pathname } = new URL(request.url, 'wss://base.url');
268+
269+ if (pathname === '/foo') {
270+ wss1.handleUpgrade(request, socket, head, function done(ws) {
271+ wss1.emit('connection', ws, request);
272+ });
273+ } else if (pathname === '/bar') {
274+ wss2.handleUpgrade(request, socket, head, function done(ws) {
275+ wss2.emit('connection', ws, request);
276+ });
277+ } else {
278+ socket.destroy();
279+ }
280+});
281+
282+server.listen(8080);
283+```
284+
285+### Client authentication
286+
287+```js
288+import { createServer } from 'http';
289+import { WebSocketServer } from 'ws';
290+
291+function onSocketError(err) {
292+ console.error(err);
293+}
294+
295+const server = createServer();
296+const wss = new WebSocketServer({ noServer: true });
297+
298+wss.on('connection', function connection(ws, request, client) {
299+ ws.on('error', console.error);
300+
301+ ws.on('message', function message(data) {
302+ console.log(`Received message ${data} from user ${client}`);
303+ });
304+});
305+
306+server.on('upgrade', function upgrade(request, socket, head) {
307+ socket.on('error', onSocketError);
308+
309+ // This function is not defined on purpose. Implement it with your own logic.
310+ authenticate(request, function next(err, client) {
311+ if (err || !client) {
312+ socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n');
313+ socket.destroy();
314+ return;
315+ }
316+
317+ socket.removeListener('error', onSocketError);
318+
319+ wss.handleUpgrade(request, socket, head, function done(ws) {
320+ wss.emit('connection', ws, request, client);
321+ });
322+ });
323+});
324+
325+server.listen(8080);
326+```
327+
328+Also see the provided [example][session-parse-example] using `express-session`.
329+
330+### Server broadcast
331+
332+A client WebSocket broadcasting to all connected WebSocket clients, including
333+itself.
334+
335+```js
336+import WebSocket, { WebSocketServer } from 'ws';
337+
338+const wss = new WebSocketServer({ port: 8080 });
339+
340+wss.on('connection', function connection(ws) {
341+ ws.on('error', console.error);
342+
343+ ws.on('message', function message(data, isBinary) {
344+ wss.clients.forEach(function each(client) {
345+ if (client.readyState === WebSocket.OPEN) {
346+ client.send(data, { binary: isBinary });
347+ }
348+ });
349+ });
350+});
351+```
352+
353+A client WebSocket broadcasting to every other connected WebSocket clients,
354+excluding itself.
355+
356+```js
357+import WebSocket, { WebSocketServer } from 'ws';
358+
359+const wss = new WebSocketServer({ port: 8080 });
360+
361+wss.on('connection', function connection(ws) {
362+ ws.on('error', console.error);
363+
364+ ws.on('message', function message(data, isBinary) {
365+ wss.clients.forEach(function each(client) {
366+ if (client !== ws && client.readyState === WebSocket.OPEN) {
367+ client.send(data, { binary: isBinary });
368+ }
369+ });
370+ });
371+});
372+```
373+
374+### Round-trip time
375+
376+```js
377+import WebSocket from 'ws';
378+
379+const ws = new WebSocket('wss://websocket-echo.com/');
380+
381+ws.on('error', console.error);
382+
383+ws.on('open', function open() {
384+ console.log('connected');
385+ ws.send(Date.now());
386+});
387+
388+ws.on('close', function close() {
389+ console.log('disconnected');
390+});
391+
392+ws.on('message', function message(data) {
393+ console.log(`Round-trip time: ${Date.now() - data} ms`);
394+
395+ setTimeout(function timeout() {
396+ ws.send(Date.now());
397+ }, 500);
398+});
399+```
400+
401+### Use the Node.js streams API
402+
403+```js
404+import WebSocket, { createWebSocketStream } from 'ws';
405+
406+const ws = new WebSocket('wss://websocket-echo.com/');
407+
408+const duplex = createWebSocketStream(ws, { encoding: 'utf8' });
409+
410+duplex.on('error', console.error);
411+
412+duplex.pipe(process.stdout);
413+process.stdin.pipe(duplex);
414+```
415+
416+### Other examples
417+
418+For a full example with a browser client communicating with a ws server, see the
419+examples folder.
420+
421+Otherwise, see the test cases.
422+
423+## FAQ
424+
425+### How to get the IP address of the client?
426+
427+The remote IP address can be obtained from the raw socket.
428+
429+```js
430+import { WebSocketServer } from 'ws';
431+
432+const wss = new WebSocketServer({ port: 8080 });
433+
434+wss.on('connection', function connection(ws, req) {
435+ const ip = req.socket.remoteAddress;
436+
437+ ws.on('error', console.error);
438+});
439+```
440+
441+When the server runs behind a proxy like NGINX, the de-facto standard is to use
442+the `X-Forwarded-For` header.
443+
444+```js
445+wss.on('connection', function connection(ws, req) {
446+ const ip = req.headers['x-forwarded-for'].split(',')[0].trim();
447+
448+ ws.on('error', console.error);
449+});
450+```
451+
452+### How to detect and close broken connections?
453+
454+Sometimes, the link between the server and the client can be interrupted in a
455+way that keeps both the server and the client unaware of the broken state of the
456+connection (e.g. when pulling the cord).
457+
458+In these cases, ping messages can be used as a means to verify that the remote
459+endpoint is still responsive.
460+
461+```js
462+import { WebSocketServer } from 'ws';
463+
464+function heartbeat() {
465+ this.isAlive = true;
466+}
467+
468+const wss = new WebSocketServer({ port: 8080 });
469+
470+wss.on('connection', function connection(ws) {
471+ ws.isAlive = true;
472+ ws.on('error', console.error);
473+ ws.on('pong', heartbeat);
474+});
475+
476+const interval = setInterval(function ping() {
477+ wss.clients.forEach(function each(ws) {
478+ if (ws.isAlive === false) return ws.terminate();
479+
480+ ws.isAlive = false;
481+ ws.ping();
482+ });
483+}, 30000);
484+
485+wss.on('close', function close() {
486+ clearInterval(interval);
487+});
488+```
489+
490+Pong messages are automatically sent in response to ping messages as required by
491+the spec.
492+
493+Just like the server example above, your clients might as well lose connection
494+without knowing it. You might want to add a ping listener on your clients to
495+prevent that. A simple implementation would be:
496+
497+```js
498+import WebSocket from 'ws';
499+
500+function heartbeat() {
501+ clearTimeout(this.pingTimeout);
502+
503+ // Use `WebSocket#terminate()`, which immediately destroys the connection,
504+ // instead of `WebSocket#close()`, which waits for the close timer.
505+ // Delay should be equal to the interval at which your server
506+ // sends out pings plus a conservative assumption of the latency.
507+ this.pingTimeout = setTimeout(() => {
508+ this.terminate();
509+ }, 30000 + 1000);
510+}
511+
512+const client = new WebSocket('wss://websocket-echo.com/');
513+
514+client.on('error', console.error);
515+client.on('open', heartbeat);
516+client.on('ping', heartbeat);
517+client.on('close', function clear() {
518+ clearTimeout(this.pingTimeout);
519+});
520+```
521+
522+### How to connect via a proxy?
523+
524+Use a custom `http.Agent` implementation like [https-proxy-agent][] or
525+[socks-proxy-agent][].
526+
527+## Changelog
528+
529+We're using the GitHub [releases][changelog] for changelog entries.
530+
531+## License
532+
533+[MIT](LICENSE)
534+
535+[`buffer.isutf8()`]: https://nodejs.org/api/buffer.html#bufferisutf8input
536+[bufferutil]: https://github.com/websockets/bufferutil
537+[changelog]: https://github.com/websockets/ws/releases
538+[client-report]: http://websockets.github.io/ws/autobahn/clients/
539+[https-proxy-agent]: https://github.com/TooTallNate/node-https-proxy-agent
540+[node-zlib-bug]: https://github.com/nodejs/node/issues/8871
541+[node-zlib-deflaterawdocs]:
542+ https://nodejs.org/api/zlib.html#zlib_zlib_createdeflateraw_options
543+[permessage-deflate]: https://tools.ietf.org/html/rfc7692
544+[server-report]: http://websockets.github.io/ws/autobahn/servers/
545+[session-parse-example]: ./examples/express-session-parse
546+[socks-proxy-agent]: https://github.com/TooTallNate/node-socks-proxy-agent
547+[utf-8-validate]: https://github.com/websockets/utf-8-validate
548+[ws-server-options]: ./doc/ws.md#new-websocketserveroptions-callback
added node_modules/ws/browser.js +8 −0
@@ -0,0 +1,8 @@
1+'use strict';
2+
3+module.exports = function () {
4+ throw new Error(
5+ 'ws does not work in the browser. Browser clients must use the native ' +
6+ 'WebSocket object'
7+ );
8+};
added node_modules/ws/index.js +22 −0
@@ -0,0 +1,22 @@
1+'use strict';
2+
3+const createWebSocketStream = require('./lib/stream');
4+const extension = require('./lib/extension');
5+const PerMessageDeflate = require('./lib/permessage-deflate');
6+const Receiver = require('./lib/receiver');
7+const Sender = require('./lib/sender');
8+const subprotocol = require('./lib/subprotocol');
9+const WebSocket = require('./lib/websocket');
10+const WebSocketServer = require('./lib/websocket-server');
11+
12+WebSocket.createWebSocketStream = createWebSocketStream;
13+WebSocket.extension = extension;
14+WebSocket.PerMessageDeflate = PerMessageDeflate;
15+WebSocket.Receiver = Receiver;
16+WebSocket.Sender = Sender;
17+WebSocket.Server = WebSocketServer;
18+WebSocket.subprotocol = subprotocol;
19+WebSocket.WebSocket = WebSocket;
20+WebSocket.WebSocketServer = WebSocketServer;
21+
22+module.exports = WebSocket;
added node_modules/ws/lib/buffer-util.js +131 −0
@@ -0,0 +1,131 @@
1+'use strict';
2+
3+const { EMPTY_BUFFER } = require('./constants');
4+
5+const FastBuffer = Buffer[Symbol.species];
6+
7+/**
8+ * Merges an array of buffers into a new buffer.
9+ *
10+ * @param {Buffer[]} list The array of buffers to concat
11+ * @param {Number} totalLength The total length of buffers in the list
12+ * @return {Buffer} The resulting buffer
13+ * @public
14+ */
15+function concat(list, totalLength) {
16+ if (list.length === 0) return EMPTY_BUFFER;
17+ if (list.length === 1) return list[0];
18+
19+ const target = Buffer.allocUnsafe(totalLength);
20+ let offset = 0;
21+
22+ for (let i = 0; i < list.length; i++) {
23+ const buf = list[i];
24+ target.set(buf, offset);
25+ offset += buf.length;
26+ }
27+
28+ if (offset < totalLength) {
29+ return new FastBuffer(target.buffer, target.byteOffset, offset);
30+ }
31+
32+ return target;
33+}
34+
35+/**
36+ * Masks a buffer using the given mask.
37+ *
38+ * @param {Buffer} source The buffer to mask
39+ * @param {Buffer} mask The mask to use
40+ * @param {Buffer} output The buffer where to store the result
41+ * @param {Number} offset The offset at which to start writing
42+ * @param {Number} length The number of bytes to mask.
43+ * @public
44+ */
45+function _mask(source, mask, output, offset, length) {
46+ for (let i = 0; i < length; i++) {
47+ output[offset + i] = source[i] ^ mask[i & 3];
48+ }
49+}
50+
51+/**
52+ * Unmasks a buffer using the given mask.
53+ *
54+ * @param {Buffer} buffer The buffer to unmask
55+ * @param {Buffer} mask The mask to use
56+ * @public
57+ */
58+function _unmask(buffer, mask) {
59+ for (let i = 0; i < buffer.length; i++) {
60+ buffer[i] ^= mask[i & 3];
61+ }
62+}
63+
64+/**
65+ * Converts a buffer to an `ArrayBuffer`.
66+ *
67+ * @param {Buffer} buf The buffer to convert
68+ * @return {ArrayBuffer} Converted buffer
69+ * @public
70+ */
71+function toArrayBuffer(buf) {
72+ if (buf.length === buf.buffer.byteLength) {
73+ return buf.buffer;
74+ }
75+
76+ return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.length);
77+}
78+
79+/**
80+ * Converts `data` to a `Buffer`.
81+ *
82+ * @param {*} data The data to convert
83+ * @return {Buffer} The buffer
84+ * @throws {TypeError}
85+ * @public
86+ */
87+function toBuffer(data) {
88+ toBuffer.readOnly = true;
89+
90+ if (Buffer.isBuffer(data)) return data;
91+
92+ let buf;
93+
94+ if (data instanceof ArrayBuffer) {
95+ buf = new FastBuffer(data);
96+ } else if (ArrayBuffer.isView(data)) {
97+ buf = new FastBuffer(data.buffer, data.byteOffset, data.byteLength);
98+ } else {
99+ buf = Buffer.from(data);
100+ toBuffer.readOnly = false;
101+ }
102+
103+ return buf;
104+}
105+
106+module.exports = {
107+ concat,
108+ mask: _mask,
109+ toArrayBuffer,
110+ toBuffer,
111+ unmask: _unmask
112+};
113+
114+/* istanbul ignore else */
115+if (!process.env.WS_NO_BUFFER_UTIL) {
116+ try {
117+ const bufferUtil = require('bufferutil');
118+
119+ module.exports.mask = function (source, mask, output, offset, length) {
120+ if (length < 48) _mask(source, mask, output, offset, length);
121+ else bufferUtil.mask(source, mask, output, offset, length);
122+ };
123+
124+ module.exports.unmask = function (buffer, mask) {
125+ if (buffer.length < 32) _unmask(buffer, mask);
126+ else bufferUtil.unmask(buffer, mask);
127+ };
128+ } catch (e) {
129+ // Continue regardless of the error.
130+ }
131+}
added node_modules/ws/lib/constants.js +19 −0
@@ -0,0 +1,19 @@
1+'use strict';
2+
3+const BINARY_TYPES = ['nodebuffer', 'arraybuffer', 'fragments'];
4+const hasBlob = typeof Blob !== 'undefined';
5+
6+if (hasBlob) BINARY_TYPES.push('blob');
7+
8+module.exports = {
9+ BINARY_TYPES,
10+ CLOSE_TIMEOUT: 30000,
11+ EMPTY_BUFFER: Buffer.alloc(0),
12+ GUID: '258EAFA5-E914-47DA-95CA-C5AB0DC85B11',
13+ hasBlob,
14+ kForOnEventAttribute: Symbol('kIsForOnEventAttribute'),
15+ kListener: Symbol('kListener'),
16+ kStatusCode: Symbol('status-code'),
17+ kWebSocket: Symbol('websocket'),
18+ NOOP: () => {}
19+};
added node_modules/ws/lib/event-target.js +292 −0
@@ -0,0 +1,292 @@
1+'use strict';
2+
3+const { kForOnEventAttribute, kListener } = require('./constants');
4+
5+const kCode = Symbol('kCode');
6+const kData = Symbol('kData');
7+const kError = Symbol('kError');
8+const kMessage = Symbol('kMessage');
9+const kReason = Symbol('kReason');
10+const kTarget = Symbol('kTarget');
11+const kType = Symbol('kType');
12+const kWasClean = Symbol('kWasClean');
13+
14+/**
15+ * Class representing an event.
16+ */
17+class Event {
18+ /**
19+ * Create a new `Event`.
20+ *
21+ * @param {String} type The name of the event
22+ * @throws {TypeError} If the `type` argument is not specified
23+ */
24+ constructor(type) {
25+ this[kTarget] = null;
26+ this[kType] = type;
27+ }
28+
29+ /**
30+ * @type {*}
31+ */
32+ get target() {
33+ return this[kTarget];
34+ }
35+
36+ /**
37+ * @type {String}
38+ */
39+ get type() {
40+ return this[kType];
41+ }
42+}
43+
44+Object.defineProperty(Event.prototype, 'target', { enumerable: true });
45+Object.defineProperty(Event.prototype, 'type', { enumerable: true });
46+
47+/**
48+ * Class representing a close event.
49+ *
50+ * @extends Event
51+ */
52+class CloseEvent extends Event {
53+ /**
54+ * Create a new `CloseEvent`.
55+ *
56+ * @param {String} type The name of the event
57+ * @param {Object} [options] A dictionary object that allows for setting
58+ * attributes via object members of the same name
59+ * @param {Number} [options.code=0] The status code explaining why the
60+ * connection was closed
61+ * @param {String} [options.reason=''] A human-readable string explaining why
62+ * the connection was closed
63+ * @param {Boolean} [options.wasClean=false] Indicates whether or not the
64+ * connection was cleanly closed
65+ */
66+ constructor(type, options = {}) {
67+ super(type);
68+
69+ this[kCode] = options.code === undefined ? 0 : options.code;
70+ this[kReason] = options.reason === undefined ? '' : options.reason;
71+ this[kWasClean] = options.wasClean === undefined ? false : options.wasClean;
72+ }
73+
74+ /**
75+ * @type {Number}
76+ */
77+ get code() {
78+ return this[kCode];
79+ }
80+
81+ /**
82+ * @type {String}
83+ */
84+ get reason() {
85+ return this[kReason];
86+ }
87+
88+ /**
89+ * @type {Boolean}
90+ */
91+ get wasClean() {
92+ return this[kWasClean];
93+ }
94+}
95+
96+Object.defineProperty(CloseEvent.prototype, 'code', { enumerable: true });
97+Object.defineProperty(CloseEvent.prototype, 'reason', { enumerable: true });
98+Object.defineProperty(CloseEvent.prototype, 'wasClean', { enumerable: true });
99+
100+/**
101+ * Class representing an error event.
102+ *
103+ * @extends Event
104+ */
105+class ErrorEvent extends Event {
106+ /**
107+ * Create a new `ErrorEvent`.
108+ *
109+ * @param {String} type The name of the event
110+ * @param {Object} [options] A dictionary object that allows for setting
111+ * attributes via object members of the same name
112+ * @param {*} [options.error=null] The error that generated this event
113+ * @param {String} [options.message=''] The error message
114+ */
115+ constructor(type, options = {}) {
116+ super(type);
117+
118+ this[kError] = options.error === undefined ? null : options.error;
119+ this[kMessage] = options.message === undefined ? '' : options.message;
120+ }
121+
122+ /**
123+ * @type {*}
124+ */
125+ get error() {
126+ return this[kError];
127+ }
128+
129+ /**
130+ * @type {String}
131+ */
132+ get message() {
133+ return this[kMessage];
134+ }
135+}
136+
137+Object.defineProperty(ErrorEvent.prototype, 'error', { enumerable: true });
138+Object.defineProperty(ErrorEvent.prototype, 'message', { enumerable: true });
139+
140+/**
141+ * Class representing a message event.
142+ *
143+ * @extends Event
144+ */
145+class MessageEvent extends Event {
146+ /**
147+ * Create a new `MessageEvent`.
148+ *
149+ * @param {String} type The name of the event
150+ * @param {Object} [options] A dictionary object that allows for setting
151+ * attributes via object members of the same name
152+ * @param {*} [options.data=null] The message content
153+ */
154+ constructor(type, options = {}) {
155+ super(type);
156+
157+ this[kData] = options.data === undefined ? null : options.data;
158+ }
159+
160+ /**
161+ * @type {*}
162+ */
163+ get data() {
164+ return this[kData];
165+ }
166+}
167+
168+Object.defineProperty(MessageEvent.prototype, 'data', { enumerable: true });
169+
170+/**
171+ * This provides methods for emulating the `EventTarget` interface. It's not
172+ * meant to be used directly.
173+ *
174+ * @mixin
175+ */
176+const EventTarget = {
177+ /**
178+ * Register an event listener.
179+ *
180+ * @param {String} type A string representing the event type to listen for
181+ * @param {(Function|Object)} handler The listener to add
182+ * @param {Object} [options] An options object specifies characteristics about
183+ * the event listener
184+ * @param {Boolean} [options.once=false] A `Boolean` indicating that the
185+ * listener should be invoked at most once after being added. If `true`,
186+ * the listener would be automatically removed when invoked.
187+ * @public
188+ */
189+ addEventListener(type, handler, options = {}) {
190+ for (const listener of this.listeners(type)) {
191+ if (
192+ !options[kForOnEventAttribute] &&
193+ listener[kListener] === handler &&
194+ !listener[kForOnEventAttribute]
195+ ) {
196+ return;
197+ }
198+ }
199+
200+ let wrapper;
201+
202+ if (type === 'message') {
203+ wrapper = function onMessage(data, isBinary) {
204+ const event = new MessageEvent('message', {
205+ data: isBinary ? data : data.toString()
206+ });
207+
208+ event[kTarget] = this;
209+ callListener(handler, this, event);
210+ };
211+ } else if (type === 'close') {
212+ wrapper = function onClose(code, message) {
213+ const event = new CloseEvent('close', {
214+ code,
215+ reason: message.toString(),
216+ wasClean: this._closeFrameReceived && this._closeFrameSent
217+ });
218+
219+ event[kTarget] = this;
220+ callListener(handler, this, event);
221+ };
222+ } else if (type === 'error') {
223+ wrapper = function onError(error) {
224+ const event = new ErrorEvent('error', {
225+ error,
226+ message: error.message
227+ });
228+
229+ event[kTarget] = this;
230+ callListener(handler, this, event);
231+ };
232+ } else if (type === 'open') {
233+ wrapper = function onOpen() {
234+ const event = new Event('open');
235+
236+ event[kTarget] = this;
237+ callListener(handler, this, event);
238+ };
239+ } else {
240+ return;
241+ }
242+
243+ wrapper[kForOnEventAttribute] = !!options[kForOnEventAttribute];
244+ wrapper[kListener] = handler;
245+
246+ if (options.once) {
247+ this.once(type, wrapper);
248+ } else {
249+ this.on(type, wrapper);
250+ }
251+ },
252+
253+ /**
254+ * Remove an event listener.
255+ *
256+ * @param {String} type A string representing the event type to remove
257+ * @param {(Function|Object)} handler The listener to remove
258+ * @public
259+ */
260+ removeEventListener(type, handler) {
261+ for (const listener of this.listeners(type)) {
262+ if (listener[kListener] === handler && !listener[kForOnEventAttribute]) {
263+ this.removeListener(type, listener);
264+ break;
265+ }
266+ }
267+ }
268+};
269+
270+module.exports = {
271+ CloseEvent,
272+ ErrorEvent,
273+ Event,
274+ EventTarget,
275+ MessageEvent
276+};
277+
278+/**
279+ * Call an event listener
280+ *
281+ * @param {(Function|Object)} listener The listener to call
282+ * @param {*} thisArg The value to use as `this`` when calling the listener
283+ * @param {Event} event The event to pass to the listener
284+ * @private
285+ */
286+function callListener(listener, thisArg, event) {
287+ if (typeof listener === 'object' && listener.handleEvent) {
288+ listener.handleEvent.call(listener, event);
289+ } else {
290+ listener.call(thisArg, event);
291+ }
292+}
added node_modules/ws/lib/extension.js +203 −0
@@ -0,0 +1,203 @@
1+'use strict';
2+
3+const { tokenChars } = require('./validation');
4+
5+/**
6+ * Adds an offer to the map of extension offers or a parameter to the map of
7+ * parameters.
8+ *
9+ * @param {Object} dest The map of extension offers or parameters
10+ * @param {String} name The extension or parameter name
11+ * @param {(Object|Boolean|String)} elem The extension parameters or the
12+ * parameter value
13+ * @private
14+ */
15+function push(dest, name, elem) {
16+ if (dest[name] === undefined) dest[name] = [elem];
17+ else dest[name].push(elem);
18+}
19+
20+/**
21+ * Parses the `Sec-WebSocket-Extensions` header into an object.
22+ *
23+ * @param {String} header The field value of the header
24+ * @return {Object} The parsed object
25+ * @public
26+ */
27+function parse(header) {
28+ const offers = Object.create(null);
29+ let params = Object.create(null);
30+ let mustUnescape = false;
31+ let isEscaping = false;
32+ let inQuotes = false;
33+ let extensionName;
34+ let paramName;
35+ let start = -1;
36+ let code = -1;
37+ let end = -1;
38+ let i = 0;
39+
40+ for (; i < header.length; i++) {
41+ code = header.charCodeAt(i);
42+
43+ if (extensionName === undefined) {
44+ if (end === -1 && tokenChars[code] === 1) {
45+ if (start === -1) start = i;
46+ } else if (
47+ i !== 0 &&
48+ (code === 0x20 /* ' ' */ || code === 0x09) /* '\t' */
49+ ) {
50+ if (end === -1 && start !== -1) end = i;
51+ } else if (code === 0x3b /* ';' */ || code === 0x2c /* ',' */) {
52+ if (start === -1) {
53+ throw new SyntaxError(`Unexpected character at index ${i}`);
54+ }
55+
56+ if (end === -1) end = i;
57+ const name = header.slice(start, end);
58+ if (code === 0x2c) {
59+ push(offers, name, params);
60+ params = Object.create(null);
61+ } else {
62+ extensionName = name;
63+ }
64+
65+ start = end = -1;
66+ } else {
67+ throw new SyntaxError(`Unexpected character at index ${i}`);
68+ }
69+ } else if (paramName === undefined) {
70+ if (end === -1 && tokenChars[code] === 1) {
71+ if (start === -1) start = i;
72+ } else if (code === 0x20 || code === 0x09) {
73+ if (end === -1 && start !== -1) end = i;
74+ } else if (code === 0x3b || code === 0x2c) {
75+ if (start === -1) {
76+ throw new SyntaxError(`Unexpected character at index ${i}`);
77+ }
78+
79+ if (end === -1) end = i;
80+ push(params, header.slice(start, end), true);
81+ if (code === 0x2c) {
82+ push(offers, extensionName, params);
83+ params = Object.create(null);
84+ extensionName = undefined;
85+ }
86+
87+ start = end = -1;
88+ } else if (code === 0x3d /* '=' */ && start !== -1 && end === -1) {
89+ paramName = header.slice(start, i);
90+ start = end = -1;
91+ } else {
92+ throw new SyntaxError(`Unexpected character at index ${i}`);
93+ }
94+ } else {
95+ //
96+ // The value of a quoted-string after unescaping must conform to the
97+ // token ABNF, so only token characters are valid.
98+ // Ref: https://tools.ietf.org/html/rfc6455#section-9.1
99+ //
100+ if (isEscaping) {
101+ if (tokenChars[code] !== 1) {
102+ throw new SyntaxError(`Unexpected character at index ${i}`);
103+ }
104+ if (start === -1) start = i;
105+ else if (!mustUnescape) mustUnescape = true;
106+ isEscaping = false;
107+ } else if (inQuotes) {
108+ if (tokenChars[code] === 1) {
109+ if (start === -1) start = i;
110+ } else if (code === 0x22 /* '"' */ && start !== -1) {
111+ inQuotes = false;
112+ end = i;
113+ } else if (code === 0x5c /* '\' */) {
114+ isEscaping = true;
115+ } else {
116+ throw new SyntaxError(`Unexpected character at index ${i}`);
117+ }
118+ } else if (code === 0x22 && header.charCodeAt(i - 1) === 0x3d) {
119+ inQuotes = true;
120+ } else if (end === -1 && tokenChars[code] === 1) {
121+ if (start === -1) start = i;
122+ } else if (start !== -1 && (code === 0x20 || code === 0x09)) {
123+ if (end === -1) end = i;
124+ } else if (code === 0x3b || code === 0x2c) {
125+ if (start === -1) {
126+ throw new SyntaxError(`Unexpected character at index ${i}`);
127+ }
128+
129+ if (end === -1) end = i;
130+ let value = header.slice(start, end);
131+ if (mustUnescape) {
132+ value = value.replace(/\\/g, '');
133+ mustUnescape = false;
134+ }
135+ push(params, paramName, value);
136+ if (code === 0x2c) {
137+ push(offers, extensionName, params);
138+ params = Object.create(null);
139+ extensionName = undefined;
140+ }
141+
142+ paramName = undefined;
143+ start = end = -1;
144+ } else {
145+ throw new SyntaxError(`Unexpected character at index ${i}`);
146+ }
147+ }
148+ }
149+
150+ if (start === -1 || inQuotes || code === 0x20 || code === 0x09) {
151+ throw new SyntaxError('Unexpected end of input');
152+ }
153+
154+ if (end === -1) end = i;
155+ const token = header.slice(start, end);
156+ if (extensionName === undefined) {
157+ push(offers, token, params);
158+ } else {
159+ if (paramName === undefined) {
160+ push(params, token, true);
161+ } else if (mustUnescape) {
162+ push(params, paramName, token.replace(/\\/g, ''));
163+ } else {
164+ push(params, paramName, token);
165+ }
166+ push(offers, extensionName, params);
167+ }
168+
169+ return offers;
170+}
171+
172+/**
173+ * Builds the `Sec-WebSocket-Extensions` header field value.
174+ *
175+ * @param {Object} extensions The map of extensions and parameters to format
176+ * @return {String} A string representing the given object
177+ * @public
178+ */
179+function format(extensions) {
180+ return Object.keys(extensions)
181+ .map((extension) => {
182+ let configurations = extensions[extension];
183+ if (!Array.isArray(configurations)) configurations = [configurations];
184+ return configurations
185+ .map((params) => {
186+ return [extension]
187+ .concat(
188+ Object.keys(params).map((k) => {
189+ let values = params[k];
190+ if (!Array.isArray(values)) values = [values];
191+ return values
192+ .map((v) => (v === true ? k : `${k}=${v}`))
193+ .join('; ');
194+ })
195+ )
196+ .join('; ');
197+ })
198+ .join(', ');
199+ })
200+ .join(', ');
201+}
202+
203+module.exports = { format, parse };
added node_modules/ws/lib/limiter.js +55 −0
Large diff (55 lines) is not loaded by default to keep the page fast.Load diff
added node_modules/ws/lib/permessage-deflate.js +530 −0
Large diff (530 lines) is not loaded by default to keep the page fast.Load diff
added node_modules/ws/lib/receiver.js +743 −0
Large diff (743 lines) is not loaded by default to keep the page fast.Load diff
added node_modules/ws/lib/sender.js +607 −0
Large diff (607 lines) is not loaded by default to keep the page fast.Load diff
added node_modules/ws/lib/stream.js +161 −0
Large diff (161 lines) is not loaded by default to keep the page fast.Load diff
added node_modules/ws/lib/subprotocol.js +62 −0
Large diff (62 lines) is not loaded by default to keep the page fast.Load diff
added node_modules/ws/lib/validation.js +152 −0
Large diff (152 lines) is not loaded by default to keep the page fast.Load diff
added node_modules/ws/lib/websocket-server.js +562 −0
Large diff (562 lines) is not loaded by default to keep the page fast.Load diff
added node_modules/ws/lib/websocket.js +1407 −0
Large diff (1,407 lines) is not loaded by default to keep the page fast.Load diff
added node_modules/ws/package.json +74 −0
Large diff (74 lines) is not loaded by default to keep the page fast.Load diff
added node_modules/ws/wrapper.mjs +21 −0
Large diff (21 lines) is not loaded by default to keep the page fast.Load diff
modified server/server.js +1 −0
Large diff (8 lines) is not loaded by default to keep the page fast.Load diff
Menu

Theme