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