cheatchat 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/commands/connect.js +29 -0
- package/src/commands/help.js +3 -0
- package/src/services/socket.js +31 -0
- package/src/ui/printer.js +64 -0
- package/src/websocket/receiver.js +47 -1
package/package.json
CHANGED
package/src/commands/connect.js
CHANGED
|
@@ -4,6 +4,7 @@ import { connectWebSocket } from "../websocket/connect.js";
|
|
|
4
4
|
import { disconnectWebSocket } from "../websocket/disconnect.js";
|
|
5
5
|
import { handleIncomingMessage } from "../websocket/receiver.js";
|
|
6
6
|
import { sendMessage } from "../websocket/sender.js";
|
|
7
|
+
import { requestHistory, requestOnline, requestUsers } from "../services/socket.js";
|
|
7
8
|
import { showChatHeader } from "../ui/banner.js";
|
|
8
9
|
import {
|
|
9
10
|
printChatHelp,
|
|
@@ -109,8 +110,13 @@ export async function connectCommand() {
|
|
|
109
110
|
showChatHeader(username, chatMode, dmTarget);
|
|
110
111
|
printBlank();
|
|
111
112
|
printSystem("You are in Global Chat. Type a message or /help for commands.");
|
|
113
|
+
printSystem("Loading chat history...");
|
|
112
114
|
printBlank();
|
|
113
115
|
|
|
116
|
+
// ─── Auto-load global history on connect ─────────────────────────────
|
|
117
|
+
|
|
118
|
+
requestHistory(ws, "global");
|
|
119
|
+
|
|
114
120
|
// ─── Start Interactive Readline ──────────────────────────────────────
|
|
115
121
|
|
|
116
122
|
rl = readline.createInterface({
|
|
@@ -141,6 +147,8 @@ export async function connectCommand() {
|
|
|
141
147
|
chatMode = CHAT_MODE.GLOBAL;
|
|
142
148
|
dmTarget = null;
|
|
143
149
|
printModeSwitch("global");
|
|
150
|
+
// Auto-load global history on mode switch
|
|
151
|
+
requestHistory(ws, "global");
|
|
144
152
|
refreshPrompt();
|
|
145
153
|
return;
|
|
146
154
|
|
|
@@ -159,10 +167,31 @@ export async function connectCommand() {
|
|
|
159
167
|
chatMode = CHAT_MODE.PRIVATE;
|
|
160
168
|
dmTarget = target;
|
|
161
169
|
printModeSwitch("private", target);
|
|
170
|
+
// Auto-load private history when switching to DM
|
|
171
|
+
requestHistory(ws, "private", target);
|
|
162
172
|
refreshPrompt();
|
|
163
173
|
return;
|
|
164
174
|
}
|
|
165
175
|
|
|
176
|
+
case "/history":
|
|
177
|
+
if (chatMode === CHAT_MODE.GLOBAL) {
|
|
178
|
+
requestHistory(ws, "global");
|
|
179
|
+
} else if (chatMode === CHAT_MODE.PRIVATE && dmTarget) {
|
|
180
|
+
requestHistory(ws, "private", dmTarget);
|
|
181
|
+
}
|
|
182
|
+
rl.prompt();
|
|
183
|
+
return;
|
|
184
|
+
|
|
185
|
+
case "/online":
|
|
186
|
+
requestOnline(ws);
|
|
187
|
+
rl.prompt();
|
|
188
|
+
return;
|
|
189
|
+
|
|
190
|
+
case "/users":
|
|
191
|
+
requestUsers(ws);
|
|
192
|
+
rl.prompt();
|
|
193
|
+
return;
|
|
194
|
+
|
|
166
195
|
case "/help":
|
|
167
196
|
printChatHelp();
|
|
168
197
|
rl.prompt();
|
package/src/commands/help.js
CHANGED
|
@@ -27,6 +27,9 @@ export function helpCommand() {
|
|
|
27
27
|
const chatCommands = [
|
|
28
28
|
["/global", "Switch to global chat"],
|
|
29
29
|
["/dm <username>", "Switch to private messaging"],
|
|
30
|
+
["/history", "Load message history"],
|
|
31
|
+
["/online", "Show online users"],
|
|
32
|
+
["/users", "Show all registered users"],
|
|
30
33
|
["/help", "Show chat commands"],
|
|
31
34
|
["/exit", "Disconnect and exit"],
|
|
32
35
|
];
|
package/src/services/socket.js
CHANGED
|
@@ -69,6 +69,37 @@ export function sendPrivateMessage(ws, to, text) {
|
|
|
69
69
|
return true;
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
+
/**
|
|
73
|
+
* Request chat history (global or private).
|
|
74
|
+
*/
|
|
75
|
+
export function requestHistory(ws, type, withUser, limit = 50) {
|
|
76
|
+
if (ws.readyState !== WebSocket.OPEN) return false;
|
|
77
|
+
const payload = { action: "history", type, limit };
|
|
78
|
+
if (type === "private" && withUser) {
|
|
79
|
+
payload.with = withUser;
|
|
80
|
+
}
|
|
81
|
+
ws.send(JSON.stringify(payload));
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Request the list of currently online users.
|
|
87
|
+
*/
|
|
88
|
+
export function requestOnline(ws) {
|
|
89
|
+
if (ws.readyState !== WebSocket.OPEN) return false;
|
|
90
|
+
ws.send(JSON.stringify({ action: "online" }));
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Request the list of all registered users.
|
|
96
|
+
*/
|
|
97
|
+
export function requestUsers(ws) {
|
|
98
|
+
if (ws.readyState !== WebSocket.OPEN) return false;
|
|
99
|
+
ws.send(JSON.stringify({ action: "users" }));
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
|
|
72
103
|
/**
|
|
73
104
|
* Close the WebSocket connection gracefully.
|
|
74
105
|
*/
|
package/src/ui/printer.js
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
warning,
|
|
14
14
|
accent,
|
|
15
15
|
brand,
|
|
16
|
+
white,
|
|
16
17
|
whiteBold,
|
|
17
18
|
dim,
|
|
18
19
|
} from "./color.js";
|
|
@@ -93,6 +94,9 @@ export function printChatHelp() {
|
|
|
93
94
|
console.log(` ${whiteBold("Chat Commands:")}`);
|
|
94
95
|
console.log(` ${brand("/global")} ${muted("Switch to global chat")}`);
|
|
95
96
|
console.log(` ${brand("/dm <username>")} ${muted("Switch to private messaging")}`);
|
|
97
|
+
console.log(` ${brand("/history")} ${muted("Load message history for current chat")}`);
|
|
98
|
+
console.log(` ${brand("/online")} ${muted("Show currently connected users")}`);
|
|
99
|
+
console.log(` ${brand("/users")} ${muted("Show all registered users")}`);
|
|
96
100
|
console.log(` ${brand("/help")} ${muted("Show this help menu")}`);
|
|
97
101
|
console.log(` ${brand("/exit")} ${muted("Disconnect and exit")}`);
|
|
98
102
|
console.log();
|
|
@@ -111,6 +115,66 @@ export function printModeSwitch(mode, target) {
|
|
|
111
115
|
console.log();
|
|
112
116
|
}
|
|
113
117
|
|
|
118
|
+
/**
|
|
119
|
+
* Print a history header.
|
|
120
|
+
*/
|
|
121
|
+
export function printHistoryHeader(type, target) {
|
|
122
|
+
console.log();
|
|
123
|
+
const sep = muted("─".repeat(50));
|
|
124
|
+
console.log(` ${sep}`);
|
|
125
|
+
if (type === "global") {
|
|
126
|
+
console.log(` ${systemTag(" HISTORY ")} ${accent("🌍 Global Chat History")}`);
|
|
127
|
+
} else {
|
|
128
|
+
console.log(` ${systemTag(" HISTORY ")} ${accent(`🔒 DM History with ${whiteBold(target)}`)}`);
|
|
129
|
+
}
|
|
130
|
+
console.log(` ${sep}`);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Print a history footer.
|
|
135
|
+
*/
|
|
136
|
+
export function printHistoryFooter(count) {
|
|
137
|
+
const sep = muted("─".repeat(50));
|
|
138
|
+
console.log(` ${sep}`);
|
|
139
|
+
console.log(` ${muted(`${count} message${count !== 1 ? "s" : ""} loaded`)}`);
|
|
140
|
+
console.log(` ${sep}`);
|
|
141
|
+
console.log();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Print online users list.
|
|
146
|
+
*/
|
|
147
|
+
export function printOnlineUsers(users) {
|
|
148
|
+
console.log();
|
|
149
|
+
console.log(` ${whiteBold("Online Users")} ${muted(`(${users.length})`)}`);
|
|
150
|
+
console.log(` ${muted("─".repeat(30))}`);
|
|
151
|
+
if (users.length === 0) {
|
|
152
|
+
console.log(` ${muted("No users online")}`);
|
|
153
|
+
} else {
|
|
154
|
+
for (const u of users) {
|
|
155
|
+
console.log(` ${success("●")} ${accent(u)}`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
console.log();
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Print all registered users list.
|
|
163
|
+
*/
|
|
164
|
+
export function printRegisteredUsers(users) {
|
|
165
|
+
console.log();
|
|
166
|
+
console.log(` ${whiteBold("Registered Users")} ${muted(`(${users.length})`)}`);
|
|
167
|
+
console.log(` ${muted("─".repeat(30))}`);
|
|
168
|
+
if (users.length === 0) {
|
|
169
|
+
console.log(` ${muted("No users found")}`);
|
|
170
|
+
} else {
|
|
171
|
+
for (const u of users) {
|
|
172
|
+
console.log(` ${brand("•")} ${white(u)}`);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
console.log();
|
|
176
|
+
}
|
|
177
|
+
|
|
114
178
|
/**
|
|
115
179
|
* Print a blank line.
|
|
116
180
|
*/
|
|
@@ -1,4 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
printGlobalMessage,
|
|
3
|
+
printPrivateMessage,
|
|
4
|
+
printError,
|
|
5
|
+
printSystem,
|
|
6
|
+
printHistoryHeader,
|
|
7
|
+
printHistoryFooter,
|
|
8
|
+
printOnlineUsers,
|
|
9
|
+
printRegisteredUsers,
|
|
10
|
+
} from "../ui/printer.js";
|
|
2
11
|
|
|
3
12
|
/**
|
|
4
13
|
* Handle incoming WebSocket messages and dispatch to the appropriate printer.
|
|
@@ -15,6 +24,18 @@ export function handleIncomingMessage(data, currentUser) {
|
|
|
15
24
|
printPrivateMessage(data.sender, data.text, data.timestamp, currentUser);
|
|
16
25
|
break;
|
|
17
26
|
|
|
27
|
+
case "history":
|
|
28
|
+
renderHistory(data, currentUser);
|
|
29
|
+
break;
|
|
30
|
+
|
|
31
|
+
case "online":
|
|
32
|
+
printOnlineUsers(data.users || []);
|
|
33
|
+
break;
|
|
34
|
+
|
|
35
|
+
case "users":
|
|
36
|
+
printRegisteredUsers(data.users || []);
|
|
37
|
+
break;
|
|
38
|
+
|
|
18
39
|
case "error":
|
|
19
40
|
printError(data.message || "Unknown server error");
|
|
20
41
|
break;
|
|
@@ -24,3 +45,28 @@ export function handleIncomingMessage(data, currentUser) {
|
|
|
24
45
|
break;
|
|
25
46
|
}
|
|
26
47
|
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Render a history response (global or private).
|
|
51
|
+
*/
|
|
52
|
+
function renderHistory(data, currentUser) {
|
|
53
|
+
const messages = data.messages || [];
|
|
54
|
+
const type = data.type;
|
|
55
|
+
const target = data.with;
|
|
56
|
+
|
|
57
|
+
printHistoryHeader(type, target);
|
|
58
|
+
|
|
59
|
+
if (messages.length === 0) {
|
|
60
|
+
printSystem("No messages yet. Start the conversation!");
|
|
61
|
+
} else {
|
|
62
|
+
for (const msg of messages) {
|
|
63
|
+
if (type === "global") {
|
|
64
|
+
printGlobalMessage(msg.sender, msg.text, msg.timestamp, currentUser);
|
|
65
|
+
} else {
|
|
66
|
+
printPrivateMessage(msg.sender, msg.text, msg.timestamp, currentUser);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
printHistoryFooter(messages.length);
|
|
72
|
+
}
|