Skip to content

Commit

Permalink
Telegram Bot Historical Events (PipedreamHQ#3429)
Browse files Browse the repository at this point in the history
* add common folder

* common webhook base

* use random uuid as webhook secret token

* get last 25 events

* fix event ts

* fix new updates summary

* change new channel updates description
  • Loading branch information
andrewjschuang authored Jul 26, 2022
1 parent 95bce05 commit 9a72c1c
Show file tree
Hide file tree
Showing 22 changed files with 177 additions and 150 deletions.
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import {
TELEGRAM_BOT_API_MEDIA_PHOTO,
TELEGRAM_BOT_API_MEDIA_VIDEO,
} from "../../constants.mjs";
} from "../../common/constants.mjs";
import telegramBotApi from "../../telegram_bot_api.app.mjs";

export default {
key: "telegram_bot_api-edit-media-message",
name: "Edit a Media Message",
description: "Edits photo or video messages. [See the docs](https://core.telegram.org/bots/api#editmessagemedia) for more information",
version: "0.0.1",
version: "0.0.2",
type: "action",
props: {
telegramBotApi,
Expand Down
4 changes: 2 additions & 2 deletions components/telegram_bot_api/actions/send-album/send-album.mjs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import telegramBotApi from "../../telegram_bot_api.app.mjs";
import { toSingleLineString } from "../../utils.mjs";
import { toSingleLineString } from "../../common/utils.mjs";

export default {
key: "telegram_bot_api-send-album",
name: "Send an Album (Media Group)",
description: "Sends a group of photos or videos as an album. [See the docs](https://core.telegram.org/bots/api#sendmediagroup) for more information",
version: "0.0.1",
version: "0.0.2",
type: "action",
props: {
telegramBotApi,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import telegramBotApi from "../../telegram_bot_api.app.mjs";
import contentTypes from "../../content-types.mjs";
import contentTypes from "../../common/content-types.mjs";

export default {
key: "telegram_bot_api-send-audio-file",
name: "Send an Audio File",
description: "Sends an audio file to your Telegram Desktop application. [See the docs](https://core.telegram.org/bots/api#sendaudio) for more information",
version: "0.0.1",
version: "0.0.2",
type: "action",
props: {
telegramBotApi,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import telegramBotApi from "../../telegram_bot_api.app.mjs";
import contentTypes from "../../content-types.mjs";
import contentTypes from "../../common/content-types.mjs";

export default {
key: "telegram_bot_api-send-document-or-image",
name: "Send a Document/Image",
description: "Sends a document or an image to your Telegram Desktop application. [See the docs](https://core.telegram.org/bots/api#senddocument) for more information",
version: "0.0.1",
version: "0.0.2",
type: "action",
props: {
telegramBotApi,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import telegramBotApi from "../../telegram_bot_api.app.mjs";
import { TELEGRAM_BOT_API_UI_MEDIA_TYPES } from "../../constants.mjs";
import { TELEGRAM_BOT_API_UI_MEDIA_TYPES } from "../../common/constants.mjs";

export default {
key: "telegram_bot_api-send-media-by-url-or-id",
name: "Send Media by URL or ID",
description: "Sends a file (document, photo, video, audio, ...) by HTTP URL or by ID that exists on the Telegram servers. [See the docs](https://core.telegram.org/bots/api#inputmedia) for more information",
version: "0.0.1",
version: "0.0.2",
type: "action",
props: {
telegramBotApi,
Expand Down
4 changes: 2 additions & 2 deletions components/telegram_bot_api/actions/send-photo/send-photo.mjs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import telegramBotApi from "../../telegram_bot_api.app.mjs";
import contentTypes from "../../content-types.mjs";
import contentTypes from "../../common/content-types.mjs";

export default {
key: "telegram_bot_api-send-photo",
name: "Send a Photo",
description: "Sends a photo to your Telegram Desktop application. [See the docs](https://core.telegram.org/bots/api#sendphoto) for more information",
version: "0.0.1",
version: "0.0.2",
type: "action",
props: {
telegramBotApi,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import telegramBotApi from "../../telegram_bot_api.app.mjs";
import contentTypes from "../../content-types.mjs";
import contentTypes from "../../common/content-types.mjs";

export default {
key: "telegram_bot_api-send-video-note",
name: "Send a Video Note",
description: "As of v.4.0, Telegram clients support rounded square mp4 videos of up to 1 minute long. Use this method to send video messages. [See the docs](https://core.telegram.org/bots/api#sendvideonote) for more information",
version: "0.0.1",
version: "0.0.2",
type: "action",
props: {
telegramBotApi,
Expand Down
4 changes: 2 additions & 2 deletions components/telegram_bot_api/actions/send-video/send-video.mjs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import telegramBotApi from "../../telegram_bot_api.app.mjs";
import contentTypes from "../../content-types.mjs";
import contentTypes from "../../common/content-types.mjs";

export default {
key: "telegram_bot_api-send-video",
name: "Send a Video",
description: "Sends a video file to your Telegram Desktop application. [See the docs](https://core.telegram.org/bots/api#sendvideo) for more information",
version: "0.0.1",
version: "0.0.2",
type: "action",
props: {
telegramBotApi,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import telegramBotApi from "../../telegram_bot_api.app.mjs";
import contentTypes from "../../content-types.mjs";
import contentTypes from "../../common/content-types.mjs";

export default {
key: "telegram_bot_api-send-voice-message",
name: "Send a Voice Message",
description: "Sends a voice message. [See the docs](https://core.telegram.org/bots/api#sendvoice) for more information",
version: "0.0.1",
version: "0.0.2",
type: "action",
props: {
telegramBotApi,
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
3 changes: 2 additions & 1 deletion components/telegram_bot_api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
"license": "MIT",
"dependencies": {
"@pipedream/platform": "^0.9.0",
"node-telegram-bot-api": "^0.54.0"
"node-telegram-bot-api": "^0.54.0",
"uuid": "^8.3.2"
},
"gitHead": "e12480b94cc03bed4808ebc6b13e7fdb3a1ba535",
"publishConfig": {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,57 +1,36 @@
// eslint-disable-next-line camelcase
import telegramBotApi from "../../telegram_bot_api.app.mjs";
import base from "../common/webhooks.mjs";

export default {
type: "source",
...base,
key: "telegram_bot_api-channel-updates",
name: "Channel Updates (Instant)",
description: "Emit new event each time a channel message is created or updated.",
version: "0.0.4",
name: "New Channel Updates (Instant)",
description: "Emit new event each time a channel post is created or updated.",
version: "0.1.0",
type: "source",
dedupe: "unique",
props: {
db: "$.service.db",
// eslint-disable-next-line pipedream/props-label,pipedream/props-description
http: {
type: "$.interface.http",
customResponse: true,
},
telegramBotApi,
},
hooks: {
async activate() {
await this.telegramBotApi.createHook(this.http.endpoint, [
methods: {
...base.methods,
getEventTypes() {
return [
"channel_post",
"edited_channel_post",
]);
];
},
async deactivate() {
await this.telegramBotApi.deleteHook();
getMeta(event, channelPost) {
return {
id: event.update_id,
summary: `${channelPost.chat.title} - ${channelPost.text}`,
ts: new Date(channelPost.edit_date ?? channelPost.date),
};
},
},
async run(event) {
// if the event doesn't contain the same API token secret,
// then it's an unauthorized replay attack.
if ((event.path).substring(1) !== this.telegramBotApi.$auth.token) {
return;
}
this.http.respond({
status: 200,
});
const { body } = event;
if (!body) {
return;
}
const channelPost = body.edited_channel_post ?? body.channel_post;
processEvent(event) {
const channelPost = event.edited_channel_post ?? event.channel_post;

if (!channelPost?.chat) {
throw new Error(`Expected body to contain a chat, but received: ${JSON.stringify(body)}`);
}
if (!channelPost?.chat) {
throw new Error(`Expected event to contain a chat, but received: ${JSON.stringify(event)}`);
}

this.$emit(body,
{
id: body.update_id,
summary: `${channelPost.chat.title} - ${channelPost.text}`,
ts: Date.now(),
});
this.$emit(event, this.getMeta(event, channelPost));
},
},
};
3 changes: 3 additions & 0 deletions components/telegram_bot_api/sources/common/constants.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default {
DEPLOY_OFFSET: -25,
};
79 changes: 79 additions & 0 deletions components/telegram_bot_api/sources/common/webhooks.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import telegramBotApi from "../../telegram_bot_api.app.mjs";
import constants from "./constants.mjs";
import { v4 as uuid } from "uuid";

export default {
props: {
telegramBotApi,
db: "$.service.db",
http: {
label: "HTTP Responder",
description: "Exposes a `respond()` method that lets the source issue HTTP responses",
type: "$.interface.http",
customResponse: true,
},
},
hooks: {
async deploy() {
/**
* From the docs: https://core.telegram.org/bots/api#getting-updates
*
* Incoming updates are stored on the server until the bot receives them either way,
* but they will not be kept longer than 24 hours.
*
* So there's a big change that no historical event is emitted.
*/
console.log("Fetching most recent events...");
const events = await this.telegramBotApi.getUpdates({
offset: constants.DEPLOY_OFFSET,
allowed_updates: this.getEventTypes(),
});
console.log(`Received ${events.length} event(s)`);
for (const event of events) {
this.processEvent(event);
}
},
async activate() {
const secret = uuid();
this.setSecret(secret);
await this.telegramBotApi.createHook(this.http.endpoint, this.getEventTypes(), secret);
},
async deactivate() {
await this.telegramBotApi.deleteHook();
},
},
methods: {
getSecret() {
return this.db.get("secret");
},
setSecret(secret) {
this.db.set("secret", secret);
},
getEventTypes() {
throw new Error("getEventTypes is not implemented");
},
processEvent() {
throw new Error("processEvent is not implemented");
},
},
async run(event) {
// check if event has the same secret
if (event.headers["x-telegram-bot-api-secret-token"] !== this.getSecret()) {
console.log("Could not identify sender identity, exiting...");
return;
}

this.http.respond({
status: 200,
});

const { body } = event;

if (!body) {
console.log("No body received, exiting...");
return;
}

this.processEvent(body);
},
};
Original file line number Diff line number Diff line change
@@ -1,50 +1,31 @@
// eslint-disable-next-line camelcase
import telegramBotApi from "../../telegram_bot_api.app.mjs";
import base from "../common/webhooks.mjs";

export default {
type: "source",
...base,
key: "telegram_bot_api-message-updates",
name: "Message Updates (Instant)",
name: "New Message Updates (Instant)",
description: "Emit new event each time a Telegram message is created or updated.",
version: "0.0.3",
version: "0.1.0",
type: "source",
dedupe: "unique",
props: {
db: "$.service.db",
// eslint-disable-next-line pipedream/props-label,pipedream/props-description
http: {
type: "$.interface.http",
customResponse: true,
methods: {
...base.methods,
getMeta(event, message) {
return {
id: event.update_id,
summary: message.text,
ts: new Date(message.edit_date ?? message.date),
};
},
telegramBotApi,
},
hooks: {
async activate() {
await this.telegramBotApi.createHook(this.http.endpoint, [
getEventTypes() {
return [
"message",
"edited_message",
]);
];
},
async deactivate() {
await this.telegramBotApi.deleteHook();
processEvent(event) {
const message = event.edited_message ?? event.message;
this.$emit(event, this.getMeta(event, message));
},
},
async run(event) {
if ((event.path).substring(1) !== this.telegramBotApi.$auth.token) {
return;
}
this.http.respond({
status: 200,
});
const { body } = event;
if (!body) {
return;
}
const message = body.edited_message ?? body.message;
this.$emit(body,
{
id: body.update_id,
summary: message.text,
ts: Date.now(),
});
},
};
Loading

0 comments on commit 9a72c1c

Please sign in to comment.