zalo-agent-cli 1.0.25 → 1.0.26

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/README.md CHANGED
@@ -160,7 +160,7 @@ zalo-agent whoami
160
160
 
161
161
  | Command | Description |
162
162
  |---------|-------------|
163
- | `msg send <threadId> <text> [-t 0\|1]` | Send text message |
163
+ | `msg send <threadId> <text> [-t 0\|1] [--md] [--style specs...]` | Send text message (with formatting) |
164
164
  | `msg send-image <threadId> <paths...> [-t 0\|1] [-m caption]` | Send images |
165
165
  | `msg send-file <threadId> <paths...> [-t 0\|1] [-m caption]` | Send files |
166
166
  | `msg send-card <threadId> <userId> [-t 0\|1] [--phone NUM]` | Send contact card |
@@ -174,6 +174,30 @@ zalo-agent whoami
174
174
 
175
175
  > `-t 0` = User (default), `-t 1` = Group
176
176
 
177
+ **Text formatting with `--md` (markdown mode):**
178
+ ```bash
179
+ zalo-agent msg send <threadId> "**Bold** *Italic* __Underline__ ~~Strike~~ {red:Red} {big:BIG}" --md
180
+ ```
181
+
182
+ | Syntax | Style |
183
+ |--------|-------|
184
+ | `**text**` | Bold |
185
+ | `*text*` | Italic |
186
+ | `__text__` | Underline |
187
+ | `~~text~~` | Strikethrough |
188
+ | `{red:text}` | Red text |
189
+ | `{orange:text}` | Orange text |
190
+ | `{yellow:text}` | Yellow text |
191
+ | `{green:text}` | Green text |
192
+ | `{big:text}` | Large font |
193
+ | `{small:text}` | Small font |
194
+
195
+ **Manual style with `--style` (for agents/automation):**
196
+ ```bash
197
+ # Format: start:len:style — style names: bold, italic, underline, strikethrough, red, orange, yellow, green, big, small
198
+ zalo-agent msg send <threadId> "Hello World" --style 0:5:bold 6:5:italic
199
+ ```
200
+
177
201
  #### Friends (`friend`)
178
202
 
179
203
  | Command | Description |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zalo-agent-cli",
3
- "version": "1.0.25",
3
+ "version": "1.0.26",
4
4
  "description": "CLI tool for Zalo automation — multi-account, proxy support, bank transfers, QR payments",
5
5
  "type": "module",
6
6
  "bin": {
@@ -7,16 +7,99 @@ import { resolve } from "path";
7
7
  import { getApi } from "../core/zalo-client.js";
8
8
  import { success, error, info, output } from "../utils/output.js";
9
9
 
10
+ /**
11
+ * TextStyle codes matching zca-js TextStyle enum.
12
+ * Used for --style option and markdown parsing.
13
+ */
14
+ const TEXT_STYLES = {
15
+ bold: "b",
16
+ b: "b",
17
+ italic: "i",
18
+ i: "i",
19
+ underline: "u",
20
+ u: "u",
21
+ strikethrough: "s",
22
+ s: "s",
23
+ red: "c_db342e",
24
+ orange: "c_f27806",
25
+ yellow: "c_f7b503",
26
+ green: "c_15a85f",
27
+ small: "f_13",
28
+ big: "f_18",
29
+ };
30
+
31
+ /**
32
+ * Parse markdown-like syntax from message text into plain text + styles array.
33
+ * Supports: **bold**, *italic*, __underline__, ~~strikethrough~~,
34
+ * {red:text}, {orange:text}, {green:text}, {yellow:text},
35
+ * {big:text}, {small:text}
36
+ */
37
+ function parseMarkdownStyles(input) {
38
+ const styles = [];
39
+ let plain = input;
40
+
41
+ // Process markdown patterns (order matters: ** before *)
42
+ const patterns = [
43
+ { regex: /\*\*(.+?)\*\*/g, st: "b" },
44
+ { regex: /\*(.+?)\*/g, st: "i" },
45
+ { regex: /__(.+?)__/g, st: "u" },
46
+ { regex: /~~(.+?)~~/g, st: "s" },
47
+ { regex: /\{(red|orange|yellow|green|big|small):(.+?)\}/g, st: null },
48
+ ];
49
+
50
+ for (const p of patterns) {
51
+ let match;
52
+ // Re-run from scratch each time since offsets shift
53
+ while ((match = p.regex.exec(plain)) !== null) {
54
+ const fullMatch = match[0];
55
+ const start = match.index;
56
+ let content, st;
57
+ if (p.st === null) {
58
+ // Color/size pattern: {color:text}
59
+ st = TEXT_STYLES[match[1]];
60
+ content = match[2];
61
+ } else {
62
+ st = p.st;
63
+ content = match[1];
64
+ }
65
+ // Replace the markdown syntax with plain content
66
+ plain = plain.slice(0, start) + content + plain.slice(start + fullMatch.length);
67
+ styles.push({ start, len: content.length, st });
68
+ // Reset regex since string changed
69
+ p.regex.lastIndex = start + content.length;
70
+ }
71
+ }
72
+
73
+ return { plain, styles };
74
+ }
75
+
76
+ /**
77
+ * Parse manual style specs: "start:len:style" → { start, len, st }
78
+ * Style names: bold, italic, underline, strikethrough, red, orange, yellow, green, big, small
79
+ */
80
+ function parseStyleSpecs(specs) {
81
+ return specs
82
+ .map((spec) => {
83
+ const [start, len, style] = spec.split(":");
84
+ const st = TEXT_STYLES[style];
85
+ if (!st) return null;
86
+ return { start: Number(start), len: Number(len), st };
87
+ })
88
+ .filter(Boolean);
89
+ }
90
+
10
91
  export function registerMsgCommands(program) {
11
92
  const msg = program.command("msg").description("Send and manage messages");
12
93
 
13
94
  msg.command("send <threadId> <message>")
14
- .description("Send a text message")
95
+ .description("Send a text message with optional formatting")
15
96
  .option("-t, --type <n>", "Thread type: 0=User, 1=Group", "0")
16
97
  .option(
17
98
  "--mention <specs...>",
18
99
  "Mention users in group message. Format: pos:userId:len (e.g. 0:USER_ID:5). Use userId=-1 for @All.",
19
100
  )
101
+ .option("--style <specs...>", "Text styles. Format: start:len:style (e.g. 0:5:bold 6:5:italic)")
102
+ .option("--md", "Parse markdown-like formatting: **bold** *italic* __underline__ ~~strike~~ {red:text}")
20
103
  .option(
21
104
  "--react <icon>",
22
105
  "Auto-react to sent message. Codes: :> (haha), /-heart (heart), /-strong (like), :o (wow), :-(( (cry), :-h (angry)",
@@ -29,8 +112,27 @@ export function registerMsgCommands(program) {
29
112
  return { pos: Number(pos), uid, len: Number(len) };
30
113
  });
31
114
 
32
- // Build message content object if mentions exist
33
- const msgContent = mentions.length > 0 ? { msg: message, mentions } : message;
115
+ // Parse text styles
116
+ let styles = [];
117
+ let finalMsg = message;
118
+
119
+ if (opts.md) {
120
+ // Markdown-like parsing: **bold** *italic* __underline__ ~~strike~~
121
+ const parsed = parseMarkdownStyles(message);
122
+ finalMsg = parsed.plain;
123
+ styles = parsed.styles;
124
+ }
125
+
126
+ if (opts.style) {
127
+ // Manual style specs: start:len:style
128
+ styles = styles.concat(parseStyleSpecs(opts.style));
129
+ }
130
+
131
+ // Build message content
132
+ const hasExtras = mentions.length > 0 || styles.length > 0;
133
+ const msgContent = hasExtras
134
+ ? { msg: finalMsg, ...(mentions.length > 0 && { mentions }), ...(styles.length > 0 && { styles }) }
135
+ : finalMsg;
34
136
 
35
137
  const cliMsgId = String(Date.now());
36
138
  const result = await getApi().sendMessage(msgContent, threadId, Number(opts.type));