pi-courier 0.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/README.md +363 -0
- package/README.zh-CN.md +362 -0
- package/deploy/pi-msg-bridge.service +26 -0
- package/deploy/pi-msg-bridge.user.service +37 -0
- package/dist/auth/challenge-auth.d.ts +76 -0
- package/dist/auth/challenge-auth.d.ts.map +1 -0
- package/dist/auth/challenge-auth.js +337 -0
- package/dist/auth/challenge-auth.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +265 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +10 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +49 -0
- package/dist/config.js.map +1 -0
- package/dist/formatting.d.ts +22 -0
- package/dist/formatting.d.ts.map +1 -0
- package/dist/formatting.js +74 -0
- package/dist/formatting.js.map +1 -0
- package/dist/lock.d.ts +3 -0
- package/dist/lock.d.ts.map +1 -0
- package/dist/lock.js +75 -0
- package/dist/lock.js.map +1 -0
- package/dist/rpc/command-map.d.ts +19 -0
- package/dist/rpc/command-map.d.ts.map +1 -0
- package/dist/rpc/command-map.js +191 -0
- package/dist/rpc/command-map.js.map +1 -0
- package/dist/rpc/message-router.d.ts +30 -0
- package/dist/rpc/message-router.d.ts.map +1 -0
- package/dist/rpc/message-router.js +110 -0
- package/dist/rpc/message-router.js.map +1 -0
- package/dist/rpc/pi-rpc.d.ts +79 -0
- package/dist/rpc/pi-rpc.d.ts.map +1 -0
- package/dist/rpc/pi-rpc.js +199 -0
- package/dist/rpc/pi-rpc.js.map +1 -0
- package/dist/setup.d.ts +10 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +159 -0
- package/dist/setup.js.map +1 -0
- package/dist/standalone.d.ts +13 -0
- package/dist/standalone.d.ts.map +1 -0
- package/dist/standalone.js +184 -0
- package/dist/standalone.js.map +1 -0
- package/dist/transports/discord.d.ts +33 -0
- package/dist/transports/discord.d.ts.map +1 -0
- package/dist/transports/discord.js +216 -0
- package/dist/transports/discord.js.map +1 -0
- package/dist/transports/interface.d.ts +42 -0
- package/dist/transports/interface.d.ts.map +1 -0
- package/dist/transports/interface.js +2 -0
- package/dist/transports/interface.js.map +1 -0
- package/dist/transports/manager.d.ts +54 -0
- package/dist/transports/manager.d.ts.map +1 -0
- package/dist/transports/manager.js +98 -0
- package/dist/transports/manager.js.map +1 -0
- package/dist/transports/matrix-utils.d.ts +31 -0
- package/dist/transports/matrix-utils.d.ts.map +1 -0
- package/dist/transports/matrix-utils.js +99 -0
- package/dist/transports/matrix-utils.js.map +1 -0
- package/dist/transports/matrix-utils.test.d.ts +2 -0
- package/dist/transports/matrix-utils.test.d.ts.map +1 -0
- package/dist/transports/matrix-utils.test.js +246 -0
- package/dist/transports/matrix-utils.test.js.map +1 -0
- package/dist/transports/matrix.d.ts +34 -0
- package/dist/transports/matrix.d.ts.map +1 -0
- package/dist/transports/matrix.js +240 -0
- package/dist/transports/matrix.js.map +1 -0
- package/dist/transports/slack.d.ts +31 -0
- package/dist/transports/slack.d.ts.map +1 -0
- package/dist/transports/slack.js +203 -0
- package/dist/transports/slack.js.map +1 -0
- package/dist/transports/telegram.d.ts +38 -0
- package/dist/transports/telegram.d.ts.map +1 -0
- package/dist/transports/telegram.js +167 -0
- package/dist/transports/telegram.js.map +1 -0
- package/dist/transports/whatsapp.d.ts +31 -0
- package/dist/transports/whatsapp.d.ts.map +1 -0
- package/dist/transports/whatsapp.js +235 -0
- package/dist/transports/whatsapp.js.map +1 -0
- package/dist/types.d.ts +69 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/extensions/index.ts +42 -0
- package/package.json +71 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import TelegramBot from "node-telegram-bot-api";
|
|
2
|
+
/**
|
|
3
|
+
* Telegram transport provider using node-telegram-bot-api
|
|
4
|
+
*/
|
|
5
|
+
export class TelegramProvider {
|
|
6
|
+
token;
|
|
7
|
+
auth;
|
|
8
|
+
type = "telegram";
|
|
9
|
+
bot;
|
|
10
|
+
_isConnected = false;
|
|
11
|
+
messageHandler;
|
|
12
|
+
errorHandler;
|
|
13
|
+
lastProcessedMessageId = 0;
|
|
14
|
+
constructor(token, auth) {
|
|
15
|
+
this.token = token;
|
|
16
|
+
this.auth = auth;
|
|
17
|
+
}
|
|
18
|
+
get isConnected() {
|
|
19
|
+
return this._isConnected;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Convert standard markdown to Telegram MarkdownV1 format.
|
|
23
|
+
*
|
|
24
|
+
* Telegram MarkdownV1 syntax: *bold*, _italic_, `code`, ```pre```, [text](url).
|
|
25
|
+
* Per docs, only `_ * [ \`` need backslash-escaping when literal — otherwise
|
|
26
|
+
* a stray `_` (e.g. in a snake_case tool name like `hud_canvas`) is parsed
|
|
27
|
+
* as an opening italic marker with no close, returning HTTP 400.
|
|
28
|
+
*
|
|
29
|
+
* Strategy: lift valid markdown patterns into NUL-sentinel placeholders,
|
|
30
|
+
* escape the remaining specials, then restore the placeholders.
|
|
31
|
+
*/
|
|
32
|
+
formatForTelegram(text) {
|
|
33
|
+
const lifted = [];
|
|
34
|
+
const lift = (s) => `\x00${lifted.push(s) - 1}\x00`;
|
|
35
|
+
// Lift valid markdown patterns in priority order — they bypass the escape step below.
|
|
36
|
+
text = text.replace(/```[\s\S]*?```/g, lift); // code blocks
|
|
37
|
+
text = text.replace(/`[^`]+`/g, lift); // inline code
|
|
38
|
+
text = text.replace(/\*\*([^*]+?)\*\*/g, (_, c) => lift(`*${c}*`)); // **bold** → *bold*
|
|
39
|
+
text = text.replace(/(?<!\*)\*(?!\*)([^*]+?)(?<!\*)\*(?!\*)/g, (_, c) => lift(`_${c}_`)); // *italic* → _italic_
|
|
40
|
+
text = text.replace(/\[[^\]]+\]\([^)]+\)/g, lift); // [text](url)
|
|
41
|
+
// Escape literal markdown specials so Telegram treats them as text.
|
|
42
|
+
text = text.replace(/[_*[`]/g, "\\$&");
|
|
43
|
+
return text.replace(/\x00(\d+)\x00/g, (_, i) => lifted[parseInt(i, 10)]);
|
|
44
|
+
}
|
|
45
|
+
async connect() {
|
|
46
|
+
if (this._isConnected)
|
|
47
|
+
return;
|
|
48
|
+
this.bot = new TelegramBot(this.token, {
|
|
49
|
+
polling: {
|
|
50
|
+
interval: 300,
|
|
51
|
+
autoStart: false,
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
// Handle incoming messages
|
|
55
|
+
this.bot.on("message", async (msg) => {
|
|
56
|
+
try {
|
|
57
|
+
await this.handleMessage(msg);
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
if (this.errorHandler) {
|
|
61
|
+
this.errorHandler(err);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
// Handle polling errors
|
|
66
|
+
this.bot.on("polling_error", (err) => {
|
|
67
|
+
if (this.errorHandler) {
|
|
68
|
+
this.errorHandler(err);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
await this.bot.startPolling();
|
|
72
|
+
this._isConnected = true;
|
|
73
|
+
}
|
|
74
|
+
async disconnect() {
|
|
75
|
+
if (!this._isConnected || !this.bot)
|
|
76
|
+
return;
|
|
77
|
+
await this.bot.stopPolling();
|
|
78
|
+
this._isConnected = false;
|
|
79
|
+
this.bot = undefined;
|
|
80
|
+
}
|
|
81
|
+
async sendMessage(chatId, text) {
|
|
82
|
+
if (!this.bot) {
|
|
83
|
+
throw new Error("Telegram bot not connected");
|
|
84
|
+
}
|
|
85
|
+
if (!text?.trim())
|
|
86
|
+
return;
|
|
87
|
+
const formattedText = this.formatForTelegram(text);
|
|
88
|
+
await this.bot.sendMessage(chatId, formattedText, { parse_mode: "Markdown" });
|
|
89
|
+
}
|
|
90
|
+
async sendTyping(chatId) {
|
|
91
|
+
if (!this.bot)
|
|
92
|
+
return;
|
|
93
|
+
await this.bot.sendChatAction(chatId, "typing");
|
|
94
|
+
}
|
|
95
|
+
onMessage(handler) {
|
|
96
|
+
this.messageHandler = handler;
|
|
97
|
+
}
|
|
98
|
+
onError(handler) {
|
|
99
|
+
this.errorHandler = handler;
|
|
100
|
+
}
|
|
101
|
+
async handleMessage(msg) {
|
|
102
|
+
// Filter out old messages (prevent stale message processing on reconnect)
|
|
103
|
+
if (msg.message_id <= this.lastProcessedMessageId) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
this.lastProcessedMessageId = msg.message_id;
|
|
107
|
+
// Only process text messages
|
|
108
|
+
if (!msg.text || !msg.from) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
const chatId = msg.chat.id.toString();
|
|
112
|
+
const userId = msg.from.id.toString();
|
|
113
|
+
const username = msg.from.username || msg.from.first_name || "unknown";
|
|
114
|
+
const isGroupChat = msg.chat.type !== "private";
|
|
115
|
+
// Check if bot was mentioned in group chat
|
|
116
|
+
let wasMentioned = false;
|
|
117
|
+
if (isGroupChat && this.bot) {
|
|
118
|
+
const botInfo = await this.bot.getMe();
|
|
119
|
+
const botUsername = botInfo.username;
|
|
120
|
+
wasMentioned =
|
|
121
|
+
msg.text.includes(`@${botUsername}`) ||
|
|
122
|
+
(msg.entities?.some((entity) => entity.type === "mention" &&
|
|
123
|
+
msg.text.substring(entity.offset, entity.offset + entity.length) ===
|
|
124
|
+
`@${botUsername}`) ?? false);
|
|
125
|
+
}
|
|
126
|
+
// Check authorization (with sendMessage callback for challenge notifications)
|
|
127
|
+
const sendMessageToUser = async (cId, text) => {
|
|
128
|
+
if (this.bot) {
|
|
129
|
+
await this.bot.sendMessage(cId, text, { parse_mode: "Markdown" });
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
const isAuthorized = await this.auth.checkAuthorization(userId, chatId, username, isGroupChat, wasMentioned, sendMessageToUser, this.type);
|
|
133
|
+
// Handle admin commands and challenge codes in DM (before auth check!)
|
|
134
|
+
if (!isGroupChat && (msg.text.startsWith("/") || msg.text.match(/^\d{6}$/))) {
|
|
135
|
+
const handled = await this.auth.handleAdminCommand(msg.text, chatId, userId, async (text) => await this.sendMessage(chatId, text), this.type);
|
|
136
|
+
if (handled) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
if (!isAuthorized) {
|
|
141
|
+
return; // Auth handler already sent challenge/error messages
|
|
142
|
+
}
|
|
143
|
+
// Strip bot mention from message if present
|
|
144
|
+
let content = msg.text;
|
|
145
|
+
if (wasMentioned && this.bot) {
|
|
146
|
+
const botInfo = await this.bot.getMe();
|
|
147
|
+
const botUsername = botInfo.username;
|
|
148
|
+
content = content.replace(new RegExp(`@${botUsername}\\s*`, "g"), "").trim();
|
|
149
|
+
}
|
|
150
|
+
// Forward to message handler
|
|
151
|
+
if (this.messageHandler && content) {
|
|
152
|
+
const externalMessage = {
|
|
153
|
+
chatId,
|
|
154
|
+
transport: this.type,
|
|
155
|
+
content,
|
|
156
|
+
username,
|
|
157
|
+
userId,
|
|
158
|
+
timestamp: new Date((msg.date || 0) * 1000),
|
|
159
|
+
messageId: msg.message_id.toString(),
|
|
160
|
+
isGroupChat,
|
|
161
|
+
wasMentioned,
|
|
162
|
+
};
|
|
163
|
+
this.messageHandler(externalMessage);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=telegram.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telegram.js","sourceRoot":"","sources":["../../src/transports/telegram.ts"],"names":[],"mappings":"AAAA,OAAO,WAAW,MAAM,uBAAuB,CAAC;AAKhD;;GAEG;AACH,MAAM,OAAO,gBAAgB;IASjB;IACA;IATD,IAAI,GAAG,UAAU,CAAC;IACnB,GAAG,CAAe;IAClB,YAAY,GAAG,KAAK,CAAC;IACrB,cAAc,CAAsC;IACpD,YAAY,CAA0B;IACtC,sBAAsB,GAAG,CAAC,CAAC;IAEnC,YACU,KAAa,EACb,IAAmB;QADnB,UAAK,GAAL,KAAK,CAAQ;QACb,SAAI,GAAJ,IAAI,CAAe;IAC1B,CAAC;IAEJ,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IAED;;;;;;;;;;OAUG;IACK,iBAAiB,CAAC,IAAY;QACpC,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,MAAM,IAAI,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC;QAE5D,sFAAsF;QACtF,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,IAAI,CAAC,CAAC,CAAC,cAAc;QAC5D,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC,CAAC,cAAc;QACrD,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,oBAAoB;QACxF,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,yCAAyC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,sBAAsB;QAChH,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,sBAAsB,EAAE,IAAI,CAAC,CAAC,CAAC,cAAc;QAEjE,oEAAoE;QACpE,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QAEvC,OAAO,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IAC3E,CAAC;IAED,KAAK,CAAC,OAAO;QACX,IAAI,IAAI,CAAC,YAAY;YAAE,OAAO;QAE9B,IAAI,CAAC,GAAG,GAAG,IAAI,WAAW,CAAC,IAAI,CAAC,KAAK,EAAE;YACrC,OAAO,EAAE;gBACP,QAAQ,EAAE,GAAG;gBACb,SAAS,EAAE,KAAK;aACjB;SACF,CAAC,CAAC;QAEH,2BAA2B;QAC3B,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;YACnC,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;YAChC,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;oBACtB,IAAI,CAAC,YAAY,CAAC,GAAY,CAAC,CAAC;gBAClC,CAAC;YACH,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,wBAAwB;QACxB,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,eAAe,EAAE,CAAC,GAAG,EAAE,EAAE;YACnC,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;gBACtB,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;YACzB,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,MAAM,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QAC9B,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,UAAU;QACd,IAAI,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,IAAI,CAAC,GAAG;YAAE,OAAO;QAE5C,MAAM,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;QAC7B,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;QAC1B,IAAI,CAAC,GAAG,GAAG,SAAS,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,MAAc,EAAE,IAAY;QAC5C,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YACd,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAChD,CAAC;QACD,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE;YAAE,OAAO;QAC1B,MAAM,aAAa,GAAG,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;QACnD,MAAM,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,MAAM,EAAE,aAAa,EAAE,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC,CAAC;IAChF,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,MAAc;QAC7B,IAAI,CAAC,IAAI,CAAC,GAAG;YAAE,OAAO;QACtB,MAAM,IAAI,CAAC,GAAG,CAAC,cAAc,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAClD,CAAC;IAED,SAAS,CAAC,OAA2C;QACnD,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC;IAChC,CAAC;IAED,OAAO,CAAC,OAA+B;QACrC,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC;IAC9B,CAAC;IAEO,KAAK,CAAC,aAAa,CAAC,GAAwB;QAClD,0EAA0E;QAC1E,IAAI,GAAG,CAAC,UAAU,IAAI,IAAI,CAAC,sBAAsB,EAAE,CAAC;YAClD,OAAO;QACT,CAAC;QACD,IAAI,CAAC,sBAAsB,GAAG,GAAG,CAAC,UAAU,CAAC;QAE7C,6BAA6B;QAC7B,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;YAC3B,OAAO;QACT,CAAC;QAED,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC;QACtC,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC;QACtC,MAAM,QAAQ,GAAG,GAAG,CAAC,IAAI,CAAC,QAAQ,IAAI,GAAG,CAAC,IAAI,CAAC,UAAU,IAAI,SAAS,CAAC;QACvE,MAAM,WAAW,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC;QAEhD,2CAA2C;QAC3C,IAAI,YAAY,GAAG,KAAK,CAAC;QACzB,IAAI,WAAW,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;YAC5B,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;YACvC,MAAM,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC;YACrC,YAAY;gBACV,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,WAAW,EAAE,CAAC;oBACpC,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CACjB,CAAC,MAAM,EAAE,EAAE,CACT,MAAM,CAAC,IAAI,KAAK,SAAS;wBACzB,GAAG,CAAC,IAAK,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;4BAC/D,IAAI,WAAW,EAAE,CACtB,IAAI,KAAK,CAAC,CAAC;QAChB,CAAC;QAED,8EAA8E;QAC9E,MAAM,iBAAiB,GAAG,KAAK,EAAE,GAAW,EAAE,IAAY,EAAE,EAAE;YAC5D,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;gBACb,MAAM,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC,CAAC;YACpE,CAAC;QACH,CAAC,CAAC;QAEF,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,kBAAkB,CACrD,MAAM,EACN,MAAM,EACN,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,IAAI,CAAC,IAAI,CACV,CAAC;QAEF,uEAAuE;QACvE,IAAI,CAAC,WAAW,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC;YAC5E,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAChD,GAAG,CAAC,IAAI,EACR,MAAM,EACN,MAAM,EACN,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,MAAM,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,EACpD,IAAI,CAAC,IAAI,CACV,CAAC;YACF,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO;YACT,CAAC;QACH,CAAC;QAED,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,OAAO,CAAC,qDAAqD;QAC/D,CAAC;QAED,4CAA4C;QAC5C,IAAI,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC;QACvB,IAAI,YAAY,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;YAC7B,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;YACvC,MAAM,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC;YACrC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,IAAI,WAAW,MAAM,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAC/E,CAAC;QAED,6BAA6B;QAC7B,IAAI,IAAI,CAAC,cAAc,IAAI,OAAO,EAAE,CAAC;YACnC,MAAM,eAAe,GAAoB;gBACvC,MAAM;gBACN,SAAS,EAAE,IAAI,CAAC,IAAI;gBACpB,OAAO;gBACP,QAAQ;gBACR,MAAM;gBACN,SAAS,EAAE,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC;gBAC3C,SAAS,EAAE,GAAG,CAAC,UAAU,CAAC,QAAQ,EAAE;gBACpC,WAAW;gBACX,YAAY;aACb,CAAC;YAEF,IAAI,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { ChallengeAuth } from "../auth/challenge-auth.js";
|
|
2
|
+
import type { ExternalMessage } from "../types.js";
|
|
3
|
+
import type { ITransportProvider } from "./interface.js";
|
|
4
|
+
/**
|
|
5
|
+
* WhatsApp transport provider using @whiskeysockets/baileys
|
|
6
|
+
*/
|
|
7
|
+
export declare class WhatsAppProvider implements ITransportProvider {
|
|
8
|
+
private auth;
|
|
9
|
+
readonly type = "whatsapp";
|
|
10
|
+
private socket;
|
|
11
|
+
private _isConnected;
|
|
12
|
+
private authPath;
|
|
13
|
+
private messageHandler?;
|
|
14
|
+
private errorHandler?;
|
|
15
|
+
private lastProcessedMessageId;
|
|
16
|
+
private debug;
|
|
17
|
+
private isManualConnect;
|
|
18
|
+
constructor(config: {
|
|
19
|
+
authPath?: string;
|
|
20
|
+
debug?: boolean;
|
|
21
|
+
}, auth: ChallengeAuth);
|
|
22
|
+
get isConnected(): boolean;
|
|
23
|
+
connect(manual?: boolean): Promise<void>;
|
|
24
|
+
disconnect(): Promise<void>;
|
|
25
|
+
sendMessage(chatId: string, text: string): Promise<void>;
|
|
26
|
+
sendTyping(chatId: string): Promise<void>;
|
|
27
|
+
onMessage(handler: (message: ExternalMessage) => void): void;
|
|
28
|
+
onError(handler: (error: Error) => void): void;
|
|
29
|
+
private handleMessage;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=whatsapp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"whatsapp.d.ts","sourceRoot":"","sources":["../../src/transports/whatsapp.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAUzD;;GAEG;AACH,qBAAa,gBAAiB,YAAW,kBAAkB;IAYvD,OAAO,CAAC,IAAI;IAXd,QAAQ,CAAC,IAAI,cAAc;IAC3B,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,cAAc,CAAC,CAAqC;IAC5D,OAAO,CAAC,YAAY,CAAC,CAAyB;IAC9C,OAAO,CAAC,sBAAsB,CAAM;IACpC,OAAO,CAAC,KAAK,CAAU;IACvB,OAAO,CAAC,eAAe,CAAS;gBAEpB,MAAM,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,EAChD,IAAI,EAAE,aAAa;IAW7B,IAAI,WAAW,IAAI,OAAO,CAEzB;IAEK,OAAO,CAAC,MAAM,GAAE,OAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IA4G/C,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAS3B,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IASxD,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB/C,SAAS,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,GAAG,IAAI;IAI5D,OAAO,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI;YAIhC,aAAa;CA0F5B"}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
import * as qrcode from "qrcode-terminal";
|
|
4
|
+
async function loadBaileys() {
|
|
5
|
+
const baileys = await import("@whiskeysockets/baileys");
|
|
6
|
+
return baileys;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* WhatsApp transport provider using @whiskeysockets/baileys
|
|
10
|
+
*/
|
|
11
|
+
export class WhatsAppProvider {
|
|
12
|
+
auth;
|
|
13
|
+
type = "whatsapp";
|
|
14
|
+
socket = null;
|
|
15
|
+
_isConnected = false;
|
|
16
|
+
authPath;
|
|
17
|
+
messageHandler;
|
|
18
|
+
errorHandler;
|
|
19
|
+
lastProcessedMessageId = "";
|
|
20
|
+
debug;
|
|
21
|
+
isManualConnect = false;
|
|
22
|
+
constructor(config, auth) {
|
|
23
|
+
this.auth = auth;
|
|
24
|
+
// Default auth path to ~/.pi/msg-bridge-whatsapp-auth
|
|
25
|
+
this.authPath = config.authPath || path.join(process.env.HOME || process.env.USERPROFILE || ".", ".pi", "msg-bridge-whatsapp-auth");
|
|
26
|
+
this.debug = config.debug || false;
|
|
27
|
+
}
|
|
28
|
+
get isConnected() {
|
|
29
|
+
return this._isConnected;
|
|
30
|
+
}
|
|
31
|
+
async connect(manual = false) {
|
|
32
|
+
if (this._isConnected)
|
|
33
|
+
return;
|
|
34
|
+
this.isManualConnect = manual;
|
|
35
|
+
// Ensure auth directory exists
|
|
36
|
+
if (!fs.existsSync(this.authPath)) {
|
|
37
|
+
fs.mkdirSync(this.authPath, { recursive: true, mode: 0o700 });
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
// Ensure existing directory has secure permissions
|
|
41
|
+
try {
|
|
42
|
+
fs.chmodSync(this.authPath, 0o700);
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
console.warn("Failed to set auth directory permissions:", err);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const baileys = await loadBaileys();
|
|
49
|
+
const { state, saveCreds } = await baileys.useMultiFileAuthState(this.authPath);
|
|
50
|
+
// Suppress Baileys logger unless debug mode
|
|
51
|
+
const silentLogger = {
|
|
52
|
+
level: 'silent',
|
|
53
|
+
child: () => silentLogger,
|
|
54
|
+
trace: () => { },
|
|
55
|
+
debug: () => { },
|
|
56
|
+
info: () => { },
|
|
57
|
+
warn: () => { },
|
|
58
|
+
error: () => { },
|
|
59
|
+
fatal: () => { },
|
|
60
|
+
};
|
|
61
|
+
this.socket = baileys.default({
|
|
62
|
+
auth: state,
|
|
63
|
+
printQRInTerminal: false, // We'll handle QR display ourselves
|
|
64
|
+
logger: this.debug ? undefined : silentLogger,
|
|
65
|
+
});
|
|
66
|
+
// Handle connection updates - set up IMMEDIATELY after socket creation
|
|
67
|
+
this.socket.ev.on("connection.update", async (update) => {
|
|
68
|
+
const { connection, lastDisconnect, qr } = update;
|
|
69
|
+
if (this.debug) {
|
|
70
|
+
console.log("[WhatsApp] connection.update event received:", JSON.stringify(update, null, 2));
|
|
71
|
+
}
|
|
72
|
+
if (qr && this.isManualConnect) {
|
|
73
|
+
console.log("\n📱 Scan this QR code with WhatsApp to authenticate:\n");
|
|
74
|
+
qrcode.generate(qr, { small: true });
|
|
75
|
+
console.log("\n");
|
|
76
|
+
}
|
|
77
|
+
if (connection === "close") {
|
|
78
|
+
const statusCode = lastDisconnect?.error?.output?.statusCode;
|
|
79
|
+
const shouldReconnect = statusCode !== baileys.DisconnectReason.loggedOut;
|
|
80
|
+
if (this.debug) {
|
|
81
|
+
console.log(`[WhatsApp] Connection closed. Status: ${statusCode}, Reconnect: ${shouldReconnect}`);
|
|
82
|
+
}
|
|
83
|
+
this._isConnected = false;
|
|
84
|
+
if (this.errorHandler && statusCode !== baileys.DisconnectReason.loggedOut) {
|
|
85
|
+
this.errorHandler(new Error(`connection closed (status ${statusCode})`));
|
|
86
|
+
}
|
|
87
|
+
// If unauthorized (401), clear invalid auth
|
|
88
|
+
if (statusCode === 401) {
|
|
89
|
+
try {
|
|
90
|
+
if (fs.existsSync(this.authPath)) {
|
|
91
|
+
fs.rmSync(this.authPath, { recursive: true, force: true });
|
|
92
|
+
if (this.isManualConnect) {
|
|
93
|
+
console.log("🔄 WhatsApp session expired. Cleared credentials. Reconnecting with QR code...");
|
|
94
|
+
// Reconnect after clearing auth to get fresh QR (manual configure only)
|
|
95
|
+
setTimeout(() => this.connect(true), 1000);
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
console.log("🔄 WhatsApp session expired. Cleared credentials. Run /msg-bridge configure whatsapp to reconnect.");
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
catch (err) {
|
|
103
|
+
console.error("Failed to clear auth:", err);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
else if (shouldReconnect) {
|
|
107
|
+
// Reconnect after 3 seconds
|
|
108
|
+
setTimeout(() => this.connect(), 3000);
|
|
109
|
+
}
|
|
110
|
+
else if (this.debug) {
|
|
111
|
+
console.warn("⚠️ WhatsApp logged out. Run /msg-bridge configure whatsapp to reconnect.");
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
else if (connection === "open") {
|
|
115
|
+
this._isConnected = true;
|
|
116
|
+
console.log("✅ WhatsApp connected!");
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
// Save credentials when updated
|
|
120
|
+
this.socket.ev.on("creds.update", saveCreds);
|
|
121
|
+
// Handle incoming messages
|
|
122
|
+
this.socket.ev.on("messages.upsert", async ({ messages, type }) => {
|
|
123
|
+
if (type !== "notify") {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
for (const msg of messages) {
|
|
127
|
+
await this.handleMessage(msg);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
async disconnect() {
|
|
132
|
+
if (!this._isConnected || !this.socket)
|
|
133
|
+
return;
|
|
134
|
+
this.socket.end(undefined);
|
|
135
|
+
this.socket = null;
|
|
136
|
+
this._isConnected = false;
|
|
137
|
+
console.log("[WhatsApp] Disconnected");
|
|
138
|
+
}
|
|
139
|
+
async sendMessage(chatId, text) {
|
|
140
|
+
if (!this.socket) {
|
|
141
|
+
throw new Error("WhatsApp not connected");
|
|
142
|
+
}
|
|
143
|
+
if (!text?.trim())
|
|
144
|
+
return;
|
|
145
|
+
await this.socket.sendMessage(chatId, { text });
|
|
146
|
+
}
|
|
147
|
+
async sendTyping(chatId) {
|
|
148
|
+
if (!this.socket)
|
|
149
|
+
return;
|
|
150
|
+
try {
|
|
151
|
+
await this.socket.sendPresenceUpdate("composing", chatId);
|
|
152
|
+
// Auto-stop composing after 3 seconds
|
|
153
|
+
setTimeout(async () => {
|
|
154
|
+
try {
|
|
155
|
+
await this.socket?.sendPresenceUpdate("paused", chatId);
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
// Ignore
|
|
159
|
+
}
|
|
160
|
+
}, 3000);
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
console.warn("[WhatsApp] Failed to send typing:", error);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
onMessage(handler) {
|
|
167
|
+
this.messageHandler = handler;
|
|
168
|
+
}
|
|
169
|
+
onError(handler) {
|
|
170
|
+
this.errorHandler = handler;
|
|
171
|
+
}
|
|
172
|
+
async handleMessage(msg) {
|
|
173
|
+
// Debug: log message structure
|
|
174
|
+
if (this.debug) {
|
|
175
|
+
console.log("[WhatsApp] Message received:", JSON.stringify(msg, null, 2));
|
|
176
|
+
}
|
|
177
|
+
// Skip non-text messages
|
|
178
|
+
const text = msg.message?.conversation || msg.message?.extendedTextMessage?.text;
|
|
179
|
+
if (!text) {
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
const messageId = msg.key.id || String(Date.now());
|
|
183
|
+
// Filter out old/duplicate messages
|
|
184
|
+
if (messageId === this.lastProcessedMessageId) {
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
this.lastProcessedMessageId = messageId;
|
|
188
|
+
const chatId = msg.key.remoteJid || "";
|
|
189
|
+
// Try multiple fields for username
|
|
190
|
+
const pushName = msg.pushName || msg.verifiedBizName || msg.key.fromMe ? "You" : "Unknown";
|
|
191
|
+
// Skip status broadcasts
|
|
192
|
+
if (chatId === "status@broadcast") {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
// Detect if DM or group
|
|
196
|
+
// Group JIDs end with @g.us, individual JIDs end with @s.whatsapp.net
|
|
197
|
+
const isGroupChat = chatId.endsWith("@g.us");
|
|
198
|
+
const userId = chatId.split("@")[0]; // Phone number
|
|
199
|
+
// For WhatsApp, mentions work differently - we'll consider it as not mentioned for now
|
|
200
|
+
const wasMentioned = false;
|
|
201
|
+
// Check authorization
|
|
202
|
+
const sendMessageToUser = async (cId, text) => {
|
|
203
|
+
if (this.socket) {
|
|
204
|
+
await this.socket.sendMessage(cId, { text });
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
const isAuthorized = await this.auth.checkAuthorization(userId, chatId, pushName, isGroupChat, wasMentioned, sendMessageToUser, this.type);
|
|
208
|
+
// Handle admin commands and challenge codes in DM
|
|
209
|
+
if (!isGroupChat && (text.startsWith("/") || text.match(/^\d{6}$/))) {
|
|
210
|
+
const handled = await this.auth.handleAdminCommand(text, chatId, userId, async (text) => await this.sendMessage(chatId, text), this.type);
|
|
211
|
+
if (handled) {
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
if (!isAuthorized) {
|
|
216
|
+
return; // Auth handler already sent challenge/error messages
|
|
217
|
+
}
|
|
218
|
+
// Forward to message handler
|
|
219
|
+
if (this.messageHandler) {
|
|
220
|
+
const externalMessage = {
|
|
221
|
+
chatId,
|
|
222
|
+
transport: this.type,
|
|
223
|
+
content: text.trim(),
|
|
224
|
+
username: pushName,
|
|
225
|
+
userId,
|
|
226
|
+
timestamp: new Date(Number(msg.messageTimestamp) * 1000),
|
|
227
|
+
messageId,
|
|
228
|
+
isGroupChat,
|
|
229
|
+
wasMentioned,
|
|
230
|
+
};
|
|
231
|
+
this.messageHandler(externalMessage);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
//# sourceMappingURL=whatsapp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"whatsapp.js","sourceRoot":"","sources":["../../src/transports/whatsapp.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External message received from a messenger transport
|
|
3
|
+
*/
|
|
4
|
+
export interface ExternalMessage {
|
|
5
|
+
/** Unique chat/channel identifier */
|
|
6
|
+
chatId: string;
|
|
7
|
+
/** Transport type (telegram, whatsapp, etc) */
|
|
8
|
+
transport: string;
|
|
9
|
+
/** Message content/text */
|
|
10
|
+
content: string;
|
|
11
|
+
/** Sender username */
|
|
12
|
+
username: string;
|
|
13
|
+
/** Sender user ID */
|
|
14
|
+
userId: string;
|
|
15
|
+
/** Message timestamp */
|
|
16
|
+
timestamp: Date;
|
|
17
|
+
/** Unique message identifier */
|
|
18
|
+
messageId: string;
|
|
19
|
+
/** Is this a group/channel message? */
|
|
20
|
+
isGroupChat: boolean;
|
|
21
|
+
/** Was the bot mentioned? (for group chats) */
|
|
22
|
+
wasMentioned?: boolean;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Configuration for msg-bridge extension
|
|
26
|
+
*/
|
|
27
|
+
export interface MsgBridgeConfig {
|
|
28
|
+
matrix?: {
|
|
29
|
+
homeserverUrl: string;
|
|
30
|
+
accessToken: string;
|
|
31
|
+
encryption?: boolean;
|
|
32
|
+
};
|
|
33
|
+
auth?: {
|
|
34
|
+
trustedUsers?: string[];
|
|
35
|
+
adminUserId?: string;
|
|
36
|
+
channels?: Record<string, {
|
|
37
|
+
enabled: boolean;
|
|
38
|
+
mode: "all" | "mentions" | "trusted-only";
|
|
39
|
+
}>;
|
|
40
|
+
};
|
|
41
|
+
hideToolCalls?: boolean;
|
|
42
|
+
autoConnect?: boolean;
|
|
43
|
+
showWidget?: boolean;
|
|
44
|
+
debug?: boolean;
|
|
45
|
+
/** pi 的工作目录(pi 子进程的 cwd;`--workdir` 参数优先) */
|
|
46
|
+
workdir?: string;
|
|
47
|
+
/** pi 会话存储目录(对应 pi 的 --session-dir) */
|
|
48
|
+
sessionDir?: string;
|
|
49
|
+
/** 显式指定 pi 的 cli.js 路径(默认:PI_CLI_PATH → which pi → 本地 node_modules) */
|
|
50
|
+
cliPath?: string;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Pending remote chat session tracking
|
|
54
|
+
*/
|
|
55
|
+
export interface PendingRemoteChat {
|
|
56
|
+
chatId: string;
|
|
57
|
+
transport: string;
|
|
58
|
+
username: string;
|
|
59
|
+
messageId: string;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Transport connection status
|
|
63
|
+
*/
|
|
64
|
+
export interface TransportStatus {
|
|
65
|
+
type: string;
|
|
66
|
+
connected: boolean;
|
|
67
|
+
error?: string;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,qCAAqC;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,+CAA+C;IAC/C,SAAS,EAAE,MAAM,CAAC;IAClB,2BAA2B;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,sBAAsB;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,qBAAqB;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,wBAAwB;IACxB,SAAS,EAAE,IAAI,CAAC;IAChB,gCAAgC;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,WAAW,EAAE,OAAO,CAAC;IACrB,+CAA+C;IAC/C,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE;QACP,aAAa,EAAE,MAAM,CAAC;QACtB,WAAW,EAAE,MAAM,CAAC;QACpB,UAAU,CAAC,EAAE,OAAO,CAAC;KACtB,CAAC;IACF,IAAI,CAAC,EAAE;QACL,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;QACxB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;YAAE,OAAO,EAAE,OAAO,CAAC;YAAC,IAAI,EAAE,KAAK,GAAG,UAAU,GAAG,cAAc,CAAA;SAAE,CAAC,CAAC;KAC5F,CAAC;IACF,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,6CAA6C;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uCAAuC;IACvC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uEAAuE;IACvE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pi extension entry — makes pi-courier discoverable in the pi
|
|
3
|
+
* package catalog (pi.dev/packages) and installable via `pi install`.
|
|
4
|
+
*
|
|
5
|
+
* The bridge itself runs as a standalone app (an RPC client of pi); this
|
|
6
|
+
* extension only registers a `/pi-courier` command that shows how to use it.
|
|
7
|
+
* It is fully self-contained (no imports) so it survives pi's production
|
|
8
|
+
* installs (`npm install --omit=dev`).
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Minimal structural type for the pi ExtensionAPI we use.
|
|
13
|
+
* (Avoids importing @earendil-works/pi-ai in the shipped extension.)
|
|
14
|
+
*/
|
|
15
|
+
interface PiApi {
|
|
16
|
+
registerCommand(
|
|
17
|
+
name: string,
|
|
18
|
+
options: {
|
|
19
|
+
description?: string;
|
|
20
|
+
handler: (args: string, ctx: { ui: { notify: (message: string, type?: string) => void } }) => Promise<void>;
|
|
21
|
+
},
|
|
22
|
+
): void;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const USAGE = [
|
|
26
|
+
"pi-courier — 通过 Matrix 远程使用 pi(消息桥接)。",
|
|
27
|
+
"",
|
|
28
|
+
"安装: npm install -g pi-courier",
|
|
29
|
+
"配置: pi-courier setup",
|
|
30
|
+
"运行: pi-courier run(前台)或 pi-courier enable(systemd 开机自启)",
|
|
31
|
+
"仓库: https://github.com/Hi-Barry/pi-courier",
|
|
32
|
+
].join("\n");
|
|
33
|
+
|
|
34
|
+
export default function register(pi: PiApi): void {
|
|
35
|
+
pi.registerCommand("pi-courier", {
|
|
36
|
+
description: "Show how to use pi-courier (run pi from Matrix)",
|
|
37
|
+
handler: async (_args, ctx) => {
|
|
38
|
+
ctx.ui.notify(USAGE, "info");
|
|
39
|
+
console.log(USAGE);
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "pi-courier",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Run pi coding agent from Matrix. Slash commands, skills and prompts fully work from messengers via the RPC protocol.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/standalone.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"pi-courier": "dist/cli.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist/",
|
|
12
|
+
"deploy/",
|
|
13
|
+
"extensions/",
|
|
14
|
+
"README.md",
|
|
15
|
+
"README.zh-CN.md"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc",
|
|
19
|
+
"prepare": "npm run build",
|
|
20
|
+
"watch": "tsc --watch",
|
|
21
|
+
"clean": "rm -rf dist",
|
|
22
|
+
"start": "node dist/standalone.js",
|
|
23
|
+
"typecheck": "tsc --noEmit",
|
|
24
|
+
"test": "vitest run",
|
|
25
|
+
"lint": "biome check src/",
|
|
26
|
+
"lint:fix": "biome check --fix src/"
|
|
27
|
+
},
|
|
28
|
+
"keywords": [
|
|
29
|
+
"pi-package",
|
|
30
|
+
"pi",
|
|
31
|
+
"pi-coding-agent",
|
|
32
|
+
"messenger",
|
|
33
|
+
"bridge",
|
|
34
|
+
"matrix",
|
|
35
|
+
"telegram",
|
|
36
|
+
"rpc",
|
|
37
|
+
"remote",
|
|
38
|
+
"chat",
|
|
39
|
+
"bot"
|
|
40
|
+
],
|
|
41
|
+
"pi": {
|
|
42
|
+
"extensions": [
|
|
43
|
+
"./extensions"
|
|
44
|
+
]
|
|
45
|
+
},
|
|
46
|
+
"license": "MIT",
|
|
47
|
+
"engines": {
|
|
48
|
+
"node": ">=20.0.0"
|
|
49
|
+
},
|
|
50
|
+
"repository": {
|
|
51
|
+
"type": "git",
|
|
52
|
+
"url": "git+https://github.com/Hi-Barry/pi-remote.git"
|
|
53
|
+
},
|
|
54
|
+
"publishConfig": {
|
|
55
|
+
"access": "public"
|
|
56
|
+
},
|
|
57
|
+
"dependencies": {
|
|
58
|
+
"matrix-bot-sdk": "^0.8.0"
|
|
59
|
+
},
|
|
60
|
+
"peerDependencies": {
|
|
61
|
+
"@earendil-works/pi-ai": ">=0.83",
|
|
62
|
+
"@earendil-works/pi-coding-agent": ">=0.83"
|
|
63
|
+
},
|
|
64
|
+
"devDependencies": {
|
|
65
|
+
"@biomejs/biome": "^2.4.14",
|
|
66
|
+
"@types/node": "^25.6.2",
|
|
67
|
+
"fast-check": "^4.5.3",
|
|
68
|
+
"typescript": "^6.0.3",
|
|
69
|
+
"vitest": "^4.1.5"
|
|
70
|
+
}
|
|
71
|
+
}
|