@pocketping/sdk-node 1.4.0 → 1.6.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/dist/index.cjs +237 -2
- package/dist/index.d.cts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +237 -2
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1241,8 +1241,38 @@ var WebhookHandler = class {
|
|
|
1241
1241
|
this.writeOK(res);
|
|
1242
1242
|
return;
|
|
1243
1243
|
}
|
|
1244
|
+
if (update.message_reaction) {
|
|
1245
|
+
const reaction = update.message_reaction;
|
|
1246
|
+
const emoji = reaction.new_reaction?.[0]?.emoji;
|
|
1247
|
+
const topicId = reaction.message_thread_id;
|
|
1248
|
+
if (emoji && emoji.includes("\u{1F5D1}") && topicId && this.config.onOperatorMessageDelete) {
|
|
1249
|
+
const deletedAt = reaction.date ? new Date(reaction.date * 1e3).toISOString() : (/* @__PURE__ */ new Date()).toISOString();
|
|
1250
|
+
await this.config.onOperatorMessageDelete(
|
|
1251
|
+
String(topicId),
|
|
1252
|
+
reaction.message_id,
|
|
1253
|
+
"telegram",
|
|
1254
|
+
deletedAt
|
|
1255
|
+
);
|
|
1256
|
+
}
|
|
1257
|
+
this.writeOK(res);
|
|
1258
|
+
return;
|
|
1259
|
+
}
|
|
1244
1260
|
if (update.message) {
|
|
1245
1261
|
const msg = update.message;
|
|
1262
|
+
if (msg.text && /^\/delete(@\w+)?(\s|$)/.test(msg.text)) {
|
|
1263
|
+
const topicId2 = msg.message_thread_id;
|
|
1264
|
+
const replyToId = msg.reply_to_message?.message_id;
|
|
1265
|
+
if (topicId2 && replyToId && this.config.onOperatorMessageDelete) {
|
|
1266
|
+
await this.config.onOperatorMessageDelete(
|
|
1267
|
+
String(topicId2),
|
|
1268
|
+
replyToId,
|
|
1269
|
+
"telegram",
|
|
1270
|
+
(/* @__PURE__ */ new Date()).toISOString()
|
|
1271
|
+
);
|
|
1272
|
+
}
|
|
1273
|
+
this.writeOK(res);
|
|
1274
|
+
return;
|
|
1275
|
+
}
|
|
1246
1276
|
if (msg.text?.startsWith("/")) {
|
|
1247
1277
|
this.writeOK(res);
|
|
1248
1278
|
return;
|
|
@@ -1567,10 +1597,140 @@ var WebhookHandler = class {
|
|
|
1567
1597
|
}
|
|
1568
1598
|
};
|
|
1569
1599
|
|
|
1600
|
+
// src/errors.ts
|
|
1601
|
+
var PocketPingSetupError = class extends Error {
|
|
1602
|
+
constructor(options) {
|
|
1603
|
+
const message = `[PocketPing] ${options.bridge} configuration error: ${options.missing} is required`;
|
|
1604
|
+
super(message);
|
|
1605
|
+
this.name = "PocketPingSetupError";
|
|
1606
|
+
this.bridge = options.bridge;
|
|
1607
|
+
this.missing = options.missing;
|
|
1608
|
+
this.guide = options.guide;
|
|
1609
|
+
this.docsUrl = options.docsUrl || `https://pocketping.io/docs/${options.bridge.toLowerCase()}`;
|
|
1610
|
+
console.error(this.getFormattedGuide());
|
|
1611
|
+
}
|
|
1612
|
+
getFormattedGuide() {
|
|
1613
|
+
return `
|
|
1614
|
+
\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510
|
|
1615
|
+
\u2502 \u26A0\uFE0F ${this.bridge} Setup Required
|
|
1616
|
+
\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524
|
|
1617
|
+
\u2502
|
|
1618
|
+
\u2502 Missing: ${this.missing}
|
|
1619
|
+
\u2502
|
|
1620
|
+
${this.guide.split("\n").map((line) => `\u2502 ${line}`).join("\n")}
|
|
1621
|
+
\u2502
|
|
1622
|
+
\u2502 \u{1F4D6} Full guide: ${this.docsUrl}
|
|
1623
|
+
\u2502
|
|
1624
|
+
\u2502 \u{1F4A1} Quick fix: npx @pocketping/cli init ${this.bridge.toLowerCase()}
|
|
1625
|
+
\u2502
|
|
1626
|
+
\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518
|
|
1627
|
+
`;
|
|
1628
|
+
}
|
|
1629
|
+
};
|
|
1630
|
+
var SETUP_GUIDES = {
|
|
1631
|
+
discord: {
|
|
1632
|
+
botToken: `
|
|
1633
|
+
To set up Discord Bot mode:
|
|
1634
|
+
|
|
1635
|
+
1. Go to https://discord.com/developers/applications
|
|
1636
|
+
2. Create a new application
|
|
1637
|
+
3. Go to Bot \u2192 Add Bot \u2192 Reset Token
|
|
1638
|
+
4. Copy the token and set DISCORD_BOT_TOKEN
|
|
1639
|
+
|
|
1640
|
+
Enable MESSAGE CONTENT INTENT in Bot settings!
|
|
1641
|
+
`,
|
|
1642
|
+
channelId: `
|
|
1643
|
+
To get your Discord Channel ID:
|
|
1644
|
+
|
|
1645
|
+
1. Enable Developer Mode in Discord:
|
|
1646
|
+
User Settings \u2192 Advanced \u2192 Developer Mode
|
|
1647
|
+
2. Right-click on your channel \u2192 Copy ID
|
|
1648
|
+
3. Set DISCORD_CHANNEL_ID in your .env
|
|
1649
|
+
|
|
1650
|
+
Tip: Use a Forum channel for organized threads!
|
|
1651
|
+
`,
|
|
1652
|
+
webhookUrl: `
|
|
1653
|
+
To get a Discord Webhook URL:
|
|
1654
|
+
|
|
1655
|
+
1. Go to your channel settings
|
|
1656
|
+
2. Integrations \u2192 Webhooks \u2192 New Webhook
|
|
1657
|
+
3. Copy the Webhook URL
|
|
1658
|
+
|
|
1659
|
+
Note: Webhooks are send-only. Use Bot mode for full features.
|
|
1660
|
+
`
|
|
1661
|
+
},
|
|
1662
|
+
slack: {
|
|
1663
|
+
botToken: `
|
|
1664
|
+
To set up Slack Bot mode:
|
|
1665
|
+
|
|
1666
|
+
1. Go to https://api.slack.com/apps
|
|
1667
|
+
2. Create New App \u2192 From scratch
|
|
1668
|
+
3. OAuth & Permissions \u2192 Add Bot Token Scopes:
|
|
1669
|
+
- chat:write, channels:read, channels:join
|
|
1670
|
+
- channels:history, groups:history, users:read
|
|
1671
|
+
4. Install to Workspace \u2192 Copy Bot Token (xoxb-...)
|
|
1672
|
+
`,
|
|
1673
|
+
channelId: `
|
|
1674
|
+
To get your Slack Channel ID:
|
|
1675
|
+
|
|
1676
|
+
1. Right-click on your channel in Slack
|
|
1677
|
+
2. View channel details
|
|
1678
|
+
3. Scroll down to find Channel ID (starts with C or G)
|
|
1679
|
+
|
|
1680
|
+
For private channels: /invite @YourBotName first
|
|
1681
|
+
`,
|
|
1682
|
+
webhookUrl: `
|
|
1683
|
+
To get a Slack Webhook URL:
|
|
1684
|
+
|
|
1685
|
+
1. Go to https://api.slack.com/apps
|
|
1686
|
+
2. Incoming Webhooks \u2192 Add New Webhook
|
|
1687
|
+
3. Select a channel \u2192 Copy Webhook URL
|
|
1688
|
+
|
|
1689
|
+
Note: Webhooks are send-only. Use Bot mode for full features.
|
|
1690
|
+
`
|
|
1691
|
+
},
|
|
1692
|
+
telegram: {
|
|
1693
|
+
botToken: `
|
|
1694
|
+
To create a Telegram Bot:
|
|
1695
|
+
|
|
1696
|
+
1. Open @BotFather in Telegram
|
|
1697
|
+
2. Send /newbot
|
|
1698
|
+
3. Choose a name and username
|
|
1699
|
+
4. Copy the Bot Token you receive
|
|
1700
|
+
|
|
1701
|
+
Set TELEGRAM_BOT_TOKEN in your .env
|
|
1702
|
+
`,
|
|
1703
|
+
chatId: `
|
|
1704
|
+
To get your Telegram Chat ID:
|
|
1705
|
+
|
|
1706
|
+
1. Create a group and enable Topics (for forums)
|
|
1707
|
+
2. Add your bot to the group as admin
|
|
1708
|
+
3. Add @getidsbot to the group
|
|
1709
|
+
4. Copy the Chat ID (starts with -100)
|
|
1710
|
+
|
|
1711
|
+
The bot needs "Manage Topics" permission!
|
|
1712
|
+
`
|
|
1713
|
+
}
|
|
1714
|
+
};
|
|
1715
|
+
|
|
1570
1716
|
// src/bridges/telegram.ts
|
|
1571
1717
|
var TelegramBridge = class {
|
|
1572
1718
|
constructor(botToken, chatId, options = {}) {
|
|
1573
1719
|
this.name = "telegram";
|
|
1720
|
+
if (!botToken) {
|
|
1721
|
+
throw new PocketPingSetupError({
|
|
1722
|
+
bridge: "Telegram",
|
|
1723
|
+
missing: "botToken",
|
|
1724
|
+
guide: SETUP_GUIDES.telegram.botToken
|
|
1725
|
+
});
|
|
1726
|
+
}
|
|
1727
|
+
if (!chatId) {
|
|
1728
|
+
throw new PocketPingSetupError({
|
|
1729
|
+
bridge: "Telegram",
|
|
1730
|
+
missing: "chatId",
|
|
1731
|
+
guide: SETUP_GUIDES.telegram.chatId
|
|
1732
|
+
});
|
|
1733
|
+
}
|
|
1574
1734
|
this.botToken = botToken;
|
|
1575
1735
|
this.chatId = chatId;
|
|
1576
1736
|
this.parseMode = options.parseMode ?? "HTML";
|
|
@@ -1739,12 +1899,14 @@ ${dataStr}
|
|
|
1739
1899
|
text = `<b>User Identified</b>
|
|
1740
1900
|
<b>ID:</b> ${this.escapeHtml(identity.id)}
|
|
1741
1901
|
` + (identity.name ? `<b>Name:</b> ${this.escapeHtml(identity.name)}
|
|
1742
|
-
` : "") + (identity.email ? `<b>Email:</b> ${this.escapeHtml(identity.email)}
|
|
1902
|
+
` : "") + (identity.email ? `<b>Email:</b> ${this.escapeHtml(identity.email)}
|
|
1903
|
+
` : "") + (session.userPhone ? `<b>Phone:</b> ${this.escapeHtml(session.userPhone)}` : "");
|
|
1743
1904
|
} else {
|
|
1744
1905
|
text = `*User Identified*
|
|
1745
1906
|
*ID:* ${this.escapeMarkdown(identity.id)}
|
|
1746
1907
|
` + (identity.name ? `*Name:* ${this.escapeMarkdown(identity.name)}
|
|
1747
|
-
` : "") + (identity.email ? `*Email:* ${this.escapeMarkdown(identity.email)}
|
|
1908
|
+
` : "") + (identity.email ? `*Email:* ${this.escapeMarkdown(identity.email)}
|
|
1909
|
+
` : "") + (session.userPhone ? `*Phone:* ${this.escapeMarkdown(session.userPhone)}` : "");
|
|
1748
1910
|
}
|
|
1749
1911
|
try {
|
|
1750
1912
|
await this.sendMessage(text.trim());
|
|
@@ -1842,6 +2004,20 @@ var DiscordBridge = class _DiscordBridge {
|
|
|
1842
2004
|
* Create a Discord bridge using a webhook URL
|
|
1843
2005
|
*/
|
|
1844
2006
|
static webhook(webhookUrl, options = {}) {
|
|
2007
|
+
if (!webhookUrl) {
|
|
2008
|
+
throw new PocketPingSetupError({
|
|
2009
|
+
bridge: "Discord",
|
|
2010
|
+
missing: "webhookUrl",
|
|
2011
|
+
guide: SETUP_GUIDES.discord.webhookUrl
|
|
2012
|
+
});
|
|
2013
|
+
}
|
|
2014
|
+
if (!webhookUrl.startsWith("https://discord.com/api/webhooks/")) {
|
|
2015
|
+
throw new PocketPingSetupError({
|
|
2016
|
+
bridge: "Discord",
|
|
2017
|
+
missing: "valid webhookUrl",
|
|
2018
|
+
guide: "Webhook URL must start with https://discord.com/api/webhooks/\n\n" + SETUP_GUIDES.discord.webhookUrl
|
|
2019
|
+
});
|
|
2020
|
+
}
|
|
1845
2021
|
return new _DiscordBridge({
|
|
1846
2022
|
mode: "webhook",
|
|
1847
2023
|
webhookUrl,
|
|
@@ -1853,6 +2029,20 @@ var DiscordBridge = class _DiscordBridge {
|
|
|
1853
2029
|
* Create a Discord bridge using a bot token
|
|
1854
2030
|
*/
|
|
1855
2031
|
static bot(botToken, channelId, options = {}) {
|
|
2032
|
+
if (!botToken) {
|
|
2033
|
+
throw new PocketPingSetupError({
|
|
2034
|
+
bridge: "Discord",
|
|
2035
|
+
missing: "botToken",
|
|
2036
|
+
guide: SETUP_GUIDES.discord.botToken
|
|
2037
|
+
});
|
|
2038
|
+
}
|
|
2039
|
+
if (!channelId) {
|
|
2040
|
+
throw new PocketPingSetupError({
|
|
2041
|
+
bridge: "Discord",
|
|
2042
|
+
missing: "channelId",
|
|
2043
|
+
guide: SETUP_GUIDES.discord.channelId
|
|
2044
|
+
});
|
|
2045
|
+
}
|
|
1856
2046
|
return new _DiscordBridge({
|
|
1857
2047
|
mode: "bot",
|
|
1858
2048
|
botToken,
|
|
@@ -2098,6 +2288,9 @@ ${JSON.stringify(event.data, null, 2)}
|
|
|
2098
2288
|
if (identity.email) {
|
|
2099
2289
|
fields.push({ name: "Email", value: identity.email, inline: true });
|
|
2100
2290
|
}
|
|
2291
|
+
if (session.userPhone) {
|
|
2292
|
+
fields.push({ name: "Phone", value: session.userPhone, inline: true });
|
|
2293
|
+
}
|
|
2101
2294
|
const embed = {
|
|
2102
2295
|
title: "User Identified",
|
|
2103
2296
|
color: 5793266,
|
|
@@ -2183,6 +2376,20 @@ var SlackBridge = class _SlackBridge {
|
|
|
2183
2376
|
* Create a Slack bridge using a webhook URL
|
|
2184
2377
|
*/
|
|
2185
2378
|
static webhook(webhookUrl, options = {}) {
|
|
2379
|
+
if (!webhookUrl) {
|
|
2380
|
+
throw new PocketPingSetupError({
|
|
2381
|
+
bridge: "Slack",
|
|
2382
|
+
missing: "webhookUrl",
|
|
2383
|
+
guide: SETUP_GUIDES.slack.webhookUrl
|
|
2384
|
+
});
|
|
2385
|
+
}
|
|
2386
|
+
if (!webhookUrl.startsWith("https://hooks.slack.com/")) {
|
|
2387
|
+
throw new PocketPingSetupError({
|
|
2388
|
+
bridge: "Slack",
|
|
2389
|
+
missing: "valid webhookUrl",
|
|
2390
|
+
guide: "Webhook URL must start with https://hooks.slack.com/\n\n" + SETUP_GUIDES.slack.webhookUrl
|
|
2391
|
+
});
|
|
2392
|
+
}
|
|
2186
2393
|
return new _SlackBridge({
|
|
2187
2394
|
mode: "webhook",
|
|
2188
2395
|
webhookUrl,
|
|
@@ -2195,6 +2402,27 @@ var SlackBridge = class _SlackBridge {
|
|
|
2195
2402
|
* Create a Slack bridge using a bot token
|
|
2196
2403
|
*/
|
|
2197
2404
|
static bot(botToken, channelId, options = {}) {
|
|
2405
|
+
if (!botToken) {
|
|
2406
|
+
throw new PocketPingSetupError({
|
|
2407
|
+
bridge: "Slack",
|
|
2408
|
+
missing: "botToken",
|
|
2409
|
+
guide: SETUP_GUIDES.slack.botToken
|
|
2410
|
+
});
|
|
2411
|
+
}
|
|
2412
|
+
if (!botToken.startsWith("xoxb-")) {
|
|
2413
|
+
throw new PocketPingSetupError({
|
|
2414
|
+
bridge: "Slack",
|
|
2415
|
+
missing: "valid botToken",
|
|
2416
|
+
guide: "Bot token must start with xoxb-\n\n" + SETUP_GUIDES.slack.botToken
|
|
2417
|
+
});
|
|
2418
|
+
}
|
|
2419
|
+
if (!channelId) {
|
|
2420
|
+
throw new PocketPingSetupError({
|
|
2421
|
+
bridge: "Slack",
|
|
2422
|
+
missing: "channelId",
|
|
2423
|
+
guide: SETUP_GUIDES.slack.channelId
|
|
2424
|
+
});
|
|
2425
|
+
}
|
|
2198
2426
|
return new _SlackBridge({
|
|
2199
2427
|
mode: "bot",
|
|
2200
2428
|
botToken,
|
|
@@ -2486,6 +2714,13 @@ ${identity.name}`
|
|
|
2486
2714
|
${identity.email}`
|
|
2487
2715
|
});
|
|
2488
2716
|
}
|
|
2717
|
+
if (session.userPhone) {
|
|
2718
|
+
fields.push({
|
|
2719
|
+
type: "mrkdwn",
|
|
2720
|
+
text: `*Phone:*
|
|
2721
|
+
${session.userPhone}`
|
|
2722
|
+
});
|
|
2723
|
+
}
|
|
2489
2724
|
const blocks = [
|
|
2490
2725
|
{
|
|
2491
2726
|
type: "header",
|
package/dist/index.d.cts
CHANGED
|
@@ -207,6 +207,10 @@ interface Session {
|
|
|
207
207
|
metadata?: SessionMetadata;
|
|
208
208
|
/** User identity if identified via PocketPing.identify() */
|
|
209
209
|
identity?: UserIdentity;
|
|
210
|
+
/** User phone from pre-chat form (E.164 format: +33612345678) */
|
|
211
|
+
userPhone?: string;
|
|
212
|
+
/** User phone country code (ISO: FR, US, etc.) */
|
|
213
|
+
userPhoneCountry?: string;
|
|
210
214
|
}
|
|
211
215
|
interface SessionMetadata {
|
|
212
216
|
url?: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -207,6 +207,10 @@ interface Session {
|
|
|
207
207
|
metadata?: SessionMetadata;
|
|
208
208
|
/** User identity if identified via PocketPing.identify() */
|
|
209
209
|
identity?: UserIdentity;
|
|
210
|
+
/** User phone from pre-chat form (E.164 format: +33612345678) */
|
|
211
|
+
userPhone?: string;
|
|
212
|
+
/** User phone country code (ISO: FR, US, etc.) */
|
|
213
|
+
userPhoneCountry?: string;
|
|
210
214
|
}
|
|
211
215
|
interface SessionMetadata {
|
|
212
216
|
url?: string;
|
package/dist/index.js
CHANGED
|
@@ -1210,8 +1210,38 @@ var WebhookHandler = class {
|
|
|
1210
1210
|
this.writeOK(res);
|
|
1211
1211
|
return;
|
|
1212
1212
|
}
|
|
1213
|
+
if (update.message_reaction) {
|
|
1214
|
+
const reaction = update.message_reaction;
|
|
1215
|
+
const emoji = reaction.new_reaction?.[0]?.emoji;
|
|
1216
|
+
const topicId = reaction.message_thread_id;
|
|
1217
|
+
if (emoji && emoji.includes("\u{1F5D1}") && topicId && this.config.onOperatorMessageDelete) {
|
|
1218
|
+
const deletedAt = reaction.date ? new Date(reaction.date * 1e3).toISOString() : (/* @__PURE__ */ new Date()).toISOString();
|
|
1219
|
+
await this.config.onOperatorMessageDelete(
|
|
1220
|
+
String(topicId),
|
|
1221
|
+
reaction.message_id,
|
|
1222
|
+
"telegram",
|
|
1223
|
+
deletedAt
|
|
1224
|
+
);
|
|
1225
|
+
}
|
|
1226
|
+
this.writeOK(res);
|
|
1227
|
+
return;
|
|
1228
|
+
}
|
|
1213
1229
|
if (update.message) {
|
|
1214
1230
|
const msg = update.message;
|
|
1231
|
+
if (msg.text && /^\/delete(@\w+)?(\s|$)/.test(msg.text)) {
|
|
1232
|
+
const topicId2 = msg.message_thread_id;
|
|
1233
|
+
const replyToId = msg.reply_to_message?.message_id;
|
|
1234
|
+
if (topicId2 && replyToId && this.config.onOperatorMessageDelete) {
|
|
1235
|
+
await this.config.onOperatorMessageDelete(
|
|
1236
|
+
String(topicId2),
|
|
1237
|
+
replyToId,
|
|
1238
|
+
"telegram",
|
|
1239
|
+
(/* @__PURE__ */ new Date()).toISOString()
|
|
1240
|
+
);
|
|
1241
|
+
}
|
|
1242
|
+
this.writeOK(res);
|
|
1243
|
+
return;
|
|
1244
|
+
}
|
|
1215
1245
|
if (msg.text?.startsWith("/")) {
|
|
1216
1246
|
this.writeOK(res);
|
|
1217
1247
|
return;
|
|
@@ -1536,10 +1566,140 @@ var WebhookHandler = class {
|
|
|
1536
1566
|
}
|
|
1537
1567
|
};
|
|
1538
1568
|
|
|
1569
|
+
// src/errors.ts
|
|
1570
|
+
var PocketPingSetupError = class extends Error {
|
|
1571
|
+
constructor(options) {
|
|
1572
|
+
const message = `[PocketPing] ${options.bridge} configuration error: ${options.missing} is required`;
|
|
1573
|
+
super(message);
|
|
1574
|
+
this.name = "PocketPingSetupError";
|
|
1575
|
+
this.bridge = options.bridge;
|
|
1576
|
+
this.missing = options.missing;
|
|
1577
|
+
this.guide = options.guide;
|
|
1578
|
+
this.docsUrl = options.docsUrl || `https://pocketping.io/docs/${options.bridge.toLowerCase()}`;
|
|
1579
|
+
console.error(this.getFormattedGuide());
|
|
1580
|
+
}
|
|
1581
|
+
getFormattedGuide() {
|
|
1582
|
+
return `
|
|
1583
|
+
\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510
|
|
1584
|
+
\u2502 \u26A0\uFE0F ${this.bridge} Setup Required
|
|
1585
|
+
\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524
|
|
1586
|
+
\u2502
|
|
1587
|
+
\u2502 Missing: ${this.missing}
|
|
1588
|
+
\u2502
|
|
1589
|
+
${this.guide.split("\n").map((line) => `\u2502 ${line}`).join("\n")}
|
|
1590
|
+
\u2502
|
|
1591
|
+
\u2502 \u{1F4D6} Full guide: ${this.docsUrl}
|
|
1592
|
+
\u2502
|
|
1593
|
+
\u2502 \u{1F4A1} Quick fix: npx @pocketping/cli init ${this.bridge.toLowerCase()}
|
|
1594
|
+
\u2502
|
|
1595
|
+
\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518
|
|
1596
|
+
`;
|
|
1597
|
+
}
|
|
1598
|
+
};
|
|
1599
|
+
var SETUP_GUIDES = {
|
|
1600
|
+
discord: {
|
|
1601
|
+
botToken: `
|
|
1602
|
+
To set up Discord Bot mode:
|
|
1603
|
+
|
|
1604
|
+
1. Go to https://discord.com/developers/applications
|
|
1605
|
+
2. Create a new application
|
|
1606
|
+
3. Go to Bot \u2192 Add Bot \u2192 Reset Token
|
|
1607
|
+
4. Copy the token and set DISCORD_BOT_TOKEN
|
|
1608
|
+
|
|
1609
|
+
Enable MESSAGE CONTENT INTENT in Bot settings!
|
|
1610
|
+
`,
|
|
1611
|
+
channelId: `
|
|
1612
|
+
To get your Discord Channel ID:
|
|
1613
|
+
|
|
1614
|
+
1. Enable Developer Mode in Discord:
|
|
1615
|
+
User Settings \u2192 Advanced \u2192 Developer Mode
|
|
1616
|
+
2. Right-click on your channel \u2192 Copy ID
|
|
1617
|
+
3. Set DISCORD_CHANNEL_ID in your .env
|
|
1618
|
+
|
|
1619
|
+
Tip: Use a Forum channel for organized threads!
|
|
1620
|
+
`,
|
|
1621
|
+
webhookUrl: `
|
|
1622
|
+
To get a Discord Webhook URL:
|
|
1623
|
+
|
|
1624
|
+
1. Go to your channel settings
|
|
1625
|
+
2. Integrations \u2192 Webhooks \u2192 New Webhook
|
|
1626
|
+
3. Copy the Webhook URL
|
|
1627
|
+
|
|
1628
|
+
Note: Webhooks are send-only. Use Bot mode for full features.
|
|
1629
|
+
`
|
|
1630
|
+
},
|
|
1631
|
+
slack: {
|
|
1632
|
+
botToken: `
|
|
1633
|
+
To set up Slack Bot mode:
|
|
1634
|
+
|
|
1635
|
+
1. Go to https://api.slack.com/apps
|
|
1636
|
+
2. Create New App \u2192 From scratch
|
|
1637
|
+
3. OAuth & Permissions \u2192 Add Bot Token Scopes:
|
|
1638
|
+
- chat:write, channels:read, channels:join
|
|
1639
|
+
- channels:history, groups:history, users:read
|
|
1640
|
+
4. Install to Workspace \u2192 Copy Bot Token (xoxb-...)
|
|
1641
|
+
`,
|
|
1642
|
+
channelId: `
|
|
1643
|
+
To get your Slack Channel ID:
|
|
1644
|
+
|
|
1645
|
+
1. Right-click on your channel in Slack
|
|
1646
|
+
2. View channel details
|
|
1647
|
+
3. Scroll down to find Channel ID (starts with C or G)
|
|
1648
|
+
|
|
1649
|
+
For private channels: /invite @YourBotName first
|
|
1650
|
+
`,
|
|
1651
|
+
webhookUrl: `
|
|
1652
|
+
To get a Slack Webhook URL:
|
|
1653
|
+
|
|
1654
|
+
1. Go to https://api.slack.com/apps
|
|
1655
|
+
2. Incoming Webhooks \u2192 Add New Webhook
|
|
1656
|
+
3. Select a channel \u2192 Copy Webhook URL
|
|
1657
|
+
|
|
1658
|
+
Note: Webhooks are send-only. Use Bot mode for full features.
|
|
1659
|
+
`
|
|
1660
|
+
},
|
|
1661
|
+
telegram: {
|
|
1662
|
+
botToken: `
|
|
1663
|
+
To create a Telegram Bot:
|
|
1664
|
+
|
|
1665
|
+
1. Open @BotFather in Telegram
|
|
1666
|
+
2. Send /newbot
|
|
1667
|
+
3. Choose a name and username
|
|
1668
|
+
4. Copy the Bot Token you receive
|
|
1669
|
+
|
|
1670
|
+
Set TELEGRAM_BOT_TOKEN in your .env
|
|
1671
|
+
`,
|
|
1672
|
+
chatId: `
|
|
1673
|
+
To get your Telegram Chat ID:
|
|
1674
|
+
|
|
1675
|
+
1. Create a group and enable Topics (for forums)
|
|
1676
|
+
2. Add your bot to the group as admin
|
|
1677
|
+
3. Add @getidsbot to the group
|
|
1678
|
+
4. Copy the Chat ID (starts with -100)
|
|
1679
|
+
|
|
1680
|
+
The bot needs "Manage Topics" permission!
|
|
1681
|
+
`
|
|
1682
|
+
}
|
|
1683
|
+
};
|
|
1684
|
+
|
|
1539
1685
|
// src/bridges/telegram.ts
|
|
1540
1686
|
var TelegramBridge = class {
|
|
1541
1687
|
constructor(botToken, chatId, options = {}) {
|
|
1542
1688
|
this.name = "telegram";
|
|
1689
|
+
if (!botToken) {
|
|
1690
|
+
throw new PocketPingSetupError({
|
|
1691
|
+
bridge: "Telegram",
|
|
1692
|
+
missing: "botToken",
|
|
1693
|
+
guide: SETUP_GUIDES.telegram.botToken
|
|
1694
|
+
});
|
|
1695
|
+
}
|
|
1696
|
+
if (!chatId) {
|
|
1697
|
+
throw new PocketPingSetupError({
|
|
1698
|
+
bridge: "Telegram",
|
|
1699
|
+
missing: "chatId",
|
|
1700
|
+
guide: SETUP_GUIDES.telegram.chatId
|
|
1701
|
+
});
|
|
1702
|
+
}
|
|
1543
1703
|
this.botToken = botToken;
|
|
1544
1704
|
this.chatId = chatId;
|
|
1545
1705
|
this.parseMode = options.parseMode ?? "HTML";
|
|
@@ -1708,12 +1868,14 @@ ${dataStr}
|
|
|
1708
1868
|
text = `<b>User Identified</b>
|
|
1709
1869
|
<b>ID:</b> ${this.escapeHtml(identity.id)}
|
|
1710
1870
|
` + (identity.name ? `<b>Name:</b> ${this.escapeHtml(identity.name)}
|
|
1711
|
-
` : "") + (identity.email ? `<b>Email:</b> ${this.escapeHtml(identity.email)}
|
|
1871
|
+
` : "") + (identity.email ? `<b>Email:</b> ${this.escapeHtml(identity.email)}
|
|
1872
|
+
` : "") + (session.userPhone ? `<b>Phone:</b> ${this.escapeHtml(session.userPhone)}` : "");
|
|
1712
1873
|
} else {
|
|
1713
1874
|
text = `*User Identified*
|
|
1714
1875
|
*ID:* ${this.escapeMarkdown(identity.id)}
|
|
1715
1876
|
` + (identity.name ? `*Name:* ${this.escapeMarkdown(identity.name)}
|
|
1716
|
-
` : "") + (identity.email ? `*Email:* ${this.escapeMarkdown(identity.email)}
|
|
1877
|
+
` : "") + (identity.email ? `*Email:* ${this.escapeMarkdown(identity.email)}
|
|
1878
|
+
` : "") + (session.userPhone ? `*Phone:* ${this.escapeMarkdown(session.userPhone)}` : "");
|
|
1717
1879
|
}
|
|
1718
1880
|
try {
|
|
1719
1881
|
await this.sendMessage(text.trim());
|
|
@@ -1811,6 +1973,20 @@ var DiscordBridge = class _DiscordBridge {
|
|
|
1811
1973
|
* Create a Discord bridge using a webhook URL
|
|
1812
1974
|
*/
|
|
1813
1975
|
static webhook(webhookUrl, options = {}) {
|
|
1976
|
+
if (!webhookUrl) {
|
|
1977
|
+
throw new PocketPingSetupError({
|
|
1978
|
+
bridge: "Discord",
|
|
1979
|
+
missing: "webhookUrl",
|
|
1980
|
+
guide: SETUP_GUIDES.discord.webhookUrl
|
|
1981
|
+
});
|
|
1982
|
+
}
|
|
1983
|
+
if (!webhookUrl.startsWith("https://discord.com/api/webhooks/")) {
|
|
1984
|
+
throw new PocketPingSetupError({
|
|
1985
|
+
bridge: "Discord",
|
|
1986
|
+
missing: "valid webhookUrl",
|
|
1987
|
+
guide: "Webhook URL must start with https://discord.com/api/webhooks/\n\n" + SETUP_GUIDES.discord.webhookUrl
|
|
1988
|
+
});
|
|
1989
|
+
}
|
|
1814
1990
|
return new _DiscordBridge({
|
|
1815
1991
|
mode: "webhook",
|
|
1816
1992
|
webhookUrl,
|
|
@@ -1822,6 +1998,20 @@ var DiscordBridge = class _DiscordBridge {
|
|
|
1822
1998
|
* Create a Discord bridge using a bot token
|
|
1823
1999
|
*/
|
|
1824
2000
|
static bot(botToken, channelId, options = {}) {
|
|
2001
|
+
if (!botToken) {
|
|
2002
|
+
throw new PocketPingSetupError({
|
|
2003
|
+
bridge: "Discord",
|
|
2004
|
+
missing: "botToken",
|
|
2005
|
+
guide: SETUP_GUIDES.discord.botToken
|
|
2006
|
+
});
|
|
2007
|
+
}
|
|
2008
|
+
if (!channelId) {
|
|
2009
|
+
throw new PocketPingSetupError({
|
|
2010
|
+
bridge: "Discord",
|
|
2011
|
+
missing: "channelId",
|
|
2012
|
+
guide: SETUP_GUIDES.discord.channelId
|
|
2013
|
+
});
|
|
2014
|
+
}
|
|
1825
2015
|
return new _DiscordBridge({
|
|
1826
2016
|
mode: "bot",
|
|
1827
2017
|
botToken,
|
|
@@ -2067,6 +2257,9 @@ ${JSON.stringify(event.data, null, 2)}
|
|
|
2067
2257
|
if (identity.email) {
|
|
2068
2258
|
fields.push({ name: "Email", value: identity.email, inline: true });
|
|
2069
2259
|
}
|
|
2260
|
+
if (session.userPhone) {
|
|
2261
|
+
fields.push({ name: "Phone", value: session.userPhone, inline: true });
|
|
2262
|
+
}
|
|
2070
2263
|
const embed = {
|
|
2071
2264
|
title: "User Identified",
|
|
2072
2265
|
color: 5793266,
|
|
@@ -2152,6 +2345,20 @@ var SlackBridge = class _SlackBridge {
|
|
|
2152
2345
|
* Create a Slack bridge using a webhook URL
|
|
2153
2346
|
*/
|
|
2154
2347
|
static webhook(webhookUrl, options = {}) {
|
|
2348
|
+
if (!webhookUrl) {
|
|
2349
|
+
throw new PocketPingSetupError({
|
|
2350
|
+
bridge: "Slack",
|
|
2351
|
+
missing: "webhookUrl",
|
|
2352
|
+
guide: SETUP_GUIDES.slack.webhookUrl
|
|
2353
|
+
});
|
|
2354
|
+
}
|
|
2355
|
+
if (!webhookUrl.startsWith("https://hooks.slack.com/")) {
|
|
2356
|
+
throw new PocketPingSetupError({
|
|
2357
|
+
bridge: "Slack",
|
|
2358
|
+
missing: "valid webhookUrl",
|
|
2359
|
+
guide: "Webhook URL must start with https://hooks.slack.com/\n\n" + SETUP_GUIDES.slack.webhookUrl
|
|
2360
|
+
});
|
|
2361
|
+
}
|
|
2155
2362
|
return new _SlackBridge({
|
|
2156
2363
|
mode: "webhook",
|
|
2157
2364
|
webhookUrl,
|
|
@@ -2164,6 +2371,27 @@ var SlackBridge = class _SlackBridge {
|
|
|
2164
2371
|
* Create a Slack bridge using a bot token
|
|
2165
2372
|
*/
|
|
2166
2373
|
static bot(botToken, channelId, options = {}) {
|
|
2374
|
+
if (!botToken) {
|
|
2375
|
+
throw new PocketPingSetupError({
|
|
2376
|
+
bridge: "Slack",
|
|
2377
|
+
missing: "botToken",
|
|
2378
|
+
guide: SETUP_GUIDES.slack.botToken
|
|
2379
|
+
});
|
|
2380
|
+
}
|
|
2381
|
+
if (!botToken.startsWith("xoxb-")) {
|
|
2382
|
+
throw new PocketPingSetupError({
|
|
2383
|
+
bridge: "Slack",
|
|
2384
|
+
missing: "valid botToken",
|
|
2385
|
+
guide: "Bot token must start with xoxb-\n\n" + SETUP_GUIDES.slack.botToken
|
|
2386
|
+
});
|
|
2387
|
+
}
|
|
2388
|
+
if (!channelId) {
|
|
2389
|
+
throw new PocketPingSetupError({
|
|
2390
|
+
bridge: "Slack",
|
|
2391
|
+
missing: "channelId",
|
|
2392
|
+
guide: SETUP_GUIDES.slack.channelId
|
|
2393
|
+
});
|
|
2394
|
+
}
|
|
2167
2395
|
return new _SlackBridge({
|
|
2168
2396
|
mode: "bot",
|
|
2169
2397
|
botToken,
|
|
@@ -2455,6 +2683,13 @@ ${identity.name}`
|
|
|
2455
2683
|
${identity.email}`
|
|
2456
2684
|
});
|
|
2457
2685
|
}
|
|
2686
|
+
if (session.userPhone) {
|
|
2687
|
+
fields.push({
|
|
2688
|
+
type: "mrkdwn",
|
|
2689
|
+
text: `*Phone:*
|
|
2690
|
+
${session.userPhone}`
|
|
2691
|
+
});
|
|
2692
|
+
}
|
|
2458
2693
|
const blocks = [
|
|
2459
2694
|
{
|
|
2460
2695
|
type: "header",
|