nyx-bot-client 0.0.2
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/.env.sample +4 -0
- package/.vscode/extensions.json +11 -0
- package/.vscode/settings.json +17 -0
- package/.zed/settings.json +20 -0
- package/@types/AcceptedGiftTypes.ts +26 -0
- package/@types/AffiliateInfo.ts +35 -0
- package/@types/Animation.ts +56 -0
- package/@types/Audio.ts +56 -0
- package/@types/BackgroundFill.ts +18 -0
- package/@types/BackgroundFillFreeformGradient.ts +16 -0
- package/@types/BackgroundFillGradient.ts +26 -0
- package/@types/BackgroundFillSolid.ts +16 -0
- package/@types/BackgroundType.ts +21 -0
- package/@types/BackgroundTypeChatTheme.ts +16 -0
- package/@types/BackgroundTypeFill.ts +23 -0
- package/@types/BackgroundTypePattern.ts +40 -0
- package/@types/BackgroundTypeWallpaper.ts +33 -0
- package/@types/Birthdate.ts +21 -0
- package/@types/BotCommand.ts +16 -0
- package/@types/BotCommandScope.ts +30 -0
- package/@types/BotCommandScopeAllChatAdministrators.ts +11 -0
- package/@types/BotCommandScopeAllGroupChats.ts +11 -0
- package/@types/BotCommandScopeAllPrivateChats.ts +11 -0
- package/@types/BotCommandScopeChat.ts +16 -0
- package/@types/BotCommandScopeChatAdministrators.ts +16 -0
- package/@types/BotCommandScopeChatMember.ts +21 -0
- package/@types/BotCommandScopeDefault.ts +12 -0
- package/@types/BotDescription.ts +11 -0
- package/@types/BotName.ts +11 -0
- package/@types/BotShortDescription.ts +11 -0
- package/@types/BusinessBotRights.ts +65 -0
- package/@types/BusinessConnection.ts +41 -0
- package/@types/BusinessIntro.ts +23 -0
- package/@types/BusinessLocation.ts +18 -0
- package/@types/BusinessMessagesDeleted.ts +24 -0
- package/@types/BusinessOpeningHours.ts +18 -0
- package/@types/BusinessOpeningHoursInterval.ts +18 -0
- package/@types/CallbackGame.ts +6 -0
- package/@types/CallbackQuery.ts +49 -0
- package/@types/Chat.ts +43 -0
- package/@types/ChatAdministratorRights.ts +84 -0
- package/@types/ChatBackground.ts +13 -0
- package/@types/ChatBoost.ts +29 -0
- package/@types/ChatBoostAdded.ts +11 -0
- package/@types/ChatBoostRemoved.ts +28 -0
- package/@types/ChatBoostSource.ts +18 -0
- package/@types/ChatBoostSourceGiftCode.ts +19 -0
- package/@types/ChatBoostSourceGiveaway.ts +35 -0
- package/@types/ChatBoostSourcePremium.ts +19 -0
- package/@types/ChatBoostUpdated.ts +18 -0
- package/@types/ChatFullInfo.ts +260 -0
- package/@types/ChatInviteLink.ts +66 -0
- package/@types/ChatJoinRequest.ts +42 -0
- package/@types/ChatLocation.ts +16 -0
- package/@types/ChatMember.ts +28 -0
- package/@types/ChatMemberAdministrator.ts +107 -0
- package/@types/ChatMemberBanned.ts +23 -0
- package/@types/ChatMemberLeft.ts +18 -0
- package/@types/ChatMemberMember.ts +23 -0
- package/@types/ChatMemberOwner.ts +28 -0
- package/@types/ChatMemberRestricted.ts +99 -0
- package/@types/ChatMemberUpdated.ts +49 -0
- package/@types/ChatPermissions.ts +78 -0
- package/@types/ChatPhoto.ts +30 -0
- package/@types/ChatShared.ts +36 -0
- package/@types/Checklist.ts +33 -0
- package/@types/ChecklistTask.ts +33 -0
- package/@types/ChecklistTasksAdded.ts +19 -0
- package/@types/ChecklistTasksDone.ts +24 -0
- package/@types/ChosenInlineResult.ts +34 -0
- package/@types/Contact.ts +33 -0
- package/@types/CopyTextButton.ts +11 -0
- package/@types/Dice.ts +17 -0
- package/@types/DirectMessagePriceChanged.ts +17 -0
- package/@types/Document.ts +41 -0
- package/@types/EncryptedCredentials.ts +23 -0
- package/@types/EncryptedPassportElement.ts +357 -0
- package/@types/ExternalReplyInfo.ts +159 -0
- package/@types/File.ts +33 -0
- package/@types/ForceReply.ts +26 -0
- package/@types/ForumTopic.ts +26 -0
- package/@types/ForumTopicClosed.ts +6 -0
- package/@types/ForumTopicCreated.ts +21 -0
- package/@types/ForumTopicEdited.ts +17 -0
- package/@types/ForumTopicReopened.ts +6 -0
- package/@types/Game.ts +41 -0
- package/@types/GameHighScore.ts +23 -0
- package/@types/GeneralForumTopicHidden.ts +7 -0
- package/@types/GeneralForumTopicUnhidden.ts +7 -0
- package/@types/Gift.ts +38 -0
- package/@types/GiftInfo.ts +52 -0
- package/@types/Gifts.ts +13 -0
- package/@types/Giveaway.ts +55 -0
- package/@types/GiveawayCompleted.ts +29 -0
- package/@types/GiveawayCreated.ts +11 -0
- package/@types/GiveawayWinners.ts +68 -0
- package/@types/InaccessibleMessage.ts +23 -0
- package/@types/InlineKeyboardButton.ts +88 -0
- package/@types/InlineKeyboardMarkup.ts +13 -0
- package/@types/InlineQuery.ts +41 -0
- package/@types/InlineQueryResult.ts +70 -0
- package/@types/InlineQueryResultArticle.ts +58 -0
- package/@types/InlineQueryResultAudio.ts +69 -0
- package/@types/InlineQueryResultCachedAudio.ts +55 -0
- package/@types/InlineQueryResultCachedDocument.ts +65 -0
- package/@types/InlineQueryResultCachedGif.ts +65 -0
- package/@types/InlineQueryResultCachedMpeg4Gif.ts +65 -0
- package/@types/InlineQueryResultCachedPhoto.ts +70 -0
- package/@types/InlineQueryResultCachedSticker.ts +34 -0
- package/@types/InlineQueryResultCachedVideo.ts +70 -0
- package/@types/InlineQueryResultCachedVoice.ts +60 -0
- package/@types/InlineQueryResultContact.ts +64 -0
- package/@types/InlineQueryResultDocument.ts +85 -0
- package/@types/InlineQueryResultGame.ts +29 -0
- package/@types/InlineQueryResultGif.ts +91 -0
- package/@types/InlineQueryResultLocation.ts +82 -0
- package/@types/InlineQueryResultMpeg4Gif.ts +91 -0
- package/@types/InlineQueryResultPhoto.ts +84 -0
- package/@types/InlineQueryResultVenue.ts +80 -0
- package/@types/InlineQueryResultVideo.ts +98 -0
- package/@types/InlineQueryResultVoice.ts +65 -0
- package/@types/InlineQueryResultsButton.ts +34 -0
- package/@types/InputChecklist.ts +39 -0
- package/@types/InputChecklistTask.ts +30 -0
- package/@types/InputContactMessageContent.ts +27 -0
- package/@types/InputFile.ts +10 -0
- package/@types/InputInvoiceMessageContent.ts +120 -0
- package/@types/InputLocationMessageContent.ts +39 -0
- package/@types/InputMedia.ts +24 -0
- package/@types/InputMediaAnimation.ts +68 -0
- package/@types/InputMediaAudio.ts +58 -0
- package/@types/InputMediaDocument.ts +49 -0
- package/@types/InputMediaPhoto.ts +45 -0
- package/@types/InputMediaVideo.ts +85 -0
- package/@types/InputMessageContent.ts +25 -0
- package/@types/InputPaidMedia.ts +11 -0
- package/@types/InputPaidMediaPhoto.ts +21 -0
- package/@types/InputPaidMediaVideo.ts +64 -0
- package/@types/InputPollOption.ts +25 -0
- package/@types/InputProfilePhoto.ts +10 -0
- package/@types/InputProfilePhotoAnimated.ts +23 -0
- package/@types/InputProfilePhotoStatic.ts +18 -0
- package/@types/InputSticker.ts +38 -0
- package/@types/InputStoryContent.ts +11 -0
- package/@types/InputStoryContentPhoto.ts +29 -0
- package/@types/InputStoryContentVideo.ts +49 -0
- package/@types/InputTextMessageContent.ts +28 -0
- package/@types/InputVenueMessageContent.ts +47 -0
- package/@types/Invoice.ts +35 -0
- package/@types/KeyboardButton.ts +61 -0
- package/@types/KeyboardButtonPollType.ts +13 -0
- package/@types/KeyboardButtonRequestChat.ts +68 -0
- package/@types/KeyboardButtonRequestUsers.ts +45 -0
- package/@types/LabeledPrice.ts +18 -0
- package/@types/LinkPreviewOptions.ts +32 -0
- package/@types/Location.ts +38 -0
- package/@types/LocationAddress.ts +26 -0
- package/@types/LoginUrl.ts +37 -0
- package/@types/MaskPosition.ts +28 -0
- package/@types/MaybeInaccessibleMessage.ts +8 -0
- package/@types/MenuButton.ts +20 -0
- package/@types/MenuButtonCommands.ts +11 -0
- package/@types/MenuButtonDefault.ts +11 -0
- package/@types/MenuButtonWebApp.ts +26 -0
- package/@types/Message.ts +608 -0
- package/@types/MessageAutoDeleteTimerChanged.ts +11 -0
- package/@types/MessageEntity.ts +109 -0
- package/@types/MessageId.ts +11 -0
- package/@types/MessageOrigin.ts +21 -0
- package/@types/MessageOriginChannel.ts +33 -0
- package/@types/MessageOriginChat.ts +28 -0
- package/@types/MessageOriginHiddenUser.ts +21 -0
- package/@types/MessageOriginUser.ts +23 -0
- package/@types/MessageReactionCountUpdated.ts +28 -0
- package/@types/MessageReactionUpdated.ts +43 -0
- package/@types/OrderInfo.ts +28 -0
- package/@types/OwnedGift.ts +11 -0
- package/@types/OwnedGiftRegular.ts +77 -0
- package/@types/OwnedGiftUnique.ts +57 -0
- package/@types/OwnedGifts.ts +23 -0
- package/@types/PaidMedia.ts +13 -0
- package/@types/PaidMediaInfo.ts +18 -0
- package/@types/PaidMediaPhoto.ts +18 -0
- package/@types/PaidMediaPreview.ts +26 -0
- package/@types/PaidMediaPurchased.ts +18 -0
- package/@types/PaidMediaVideo.ts +18 -0
- package/@types/PaidMessagePriceChanged.ts +16 -0
- package/@types/PassportData.ts +18 -0
- package/@types/PassportElementError.ts +37 -0
- package/@types/PassportElementErrorDataField.ts +39 -0
- package/@types/PassportElementErrorFile.ts +33 -0
- package/@types/PassportElementErrorFiles.ts +33 -0
- package/@types/PassportElementErrorFrontSide.ts +28 -0
- package/@types/PassportElementErrorReverseSide.ts +27 -0
- package/@types/PassportElementErrorSelfie.ts +28 -0
- package/@types/PassportElementErrorTranslationFile.ts +38 -0
- package/@types/PassportElementErrorTranslationFiles.ts +38 -0
- package/@types/PassportElementErrorUnspecified.ts +49 -0
- package/@types/PassportFile.ts +28 -0
- package/@types/PhotoSize.ts +32 -0
- package/@types/Poll.ts +81 -0
- package/@types/PollAnswer.ts +28 -0
- package/@types/PollOption.ts +24 -0
- package/@types/PreCheckoutQuery.ts +45 -0
- package/@types/ProximityAlertTriggered.ts +24 -0
- package/@types/ReactionCount.ts +18 -0
- package/@types/ReactionType.ts +18 -0
- package/@types/ReactionTypeCustomEmoji.ts +16 -0
- package/@types/ReactionTypeEmoji.ts +92 -0
- package/@types/ReactionTypePaid.ts +11 -0
- package/@types/RefundedPayment.ts +35 -0
- package/@types/ReplyKeyboardMarkup.ts +49 -0
- package/@types/ReplyKeyboardRemove.ts +25 -0
- package/@types/ReplyParameters.ts +48 -0
- package/@types/ResponseParameters.ts +19 -0
- package/@types/RevenueWithdrawalState.ts +13 -0
- package/@types/RevenueWithdrawalStateFailed.ts +11 -0
- package/@types/RevenueWithdrawalStatePending.ts +10 -0
- package/@types/RevenueWithdrawalStateSucceeded.ts +21 -0
- package/@types/SentWebAppMessage.ts +12 -0
- package/@types/SharedUser.ts +36 -0
- package/@types/ShippingAddress.ts +36 -0
- package/@types/ShippingOption.ts +23 -0
- package/@types/ShippingQuery.ts +28 -0
- package/@types/StarAmount.ts +17 -0
- package/@types/StarTransaction.ts +42 -0
- package/@types/StarTransactions.ts +13 -0
- package/@types/Sticker.ts +86 -0
- package/@types/StickerSet.ts +33 -0
- package/@types/Story.ts +18 -0
- package/@types/StoryArea.ts +18 -0
- package/@types/StoryAreaPosition.ts +36 -0
- package/@types/StoryAreaType.ts +24 -0
- package/@types/StoryAreaTypeLink.ts +16 -0
- package/@types/StoryAreaTypeLocation.ts +28 -0
- package/@types/StoryAreaTypeSuggestedReaction.ts +29 -0
- package/@types/StoryAreaTypeUniqueGift.ts +16 -0
- package/@types/StoryAreaTypeWeather.ts +26 -0
- package/@types/SuccessfulPayment.ts +60 -0
- package/@types/SwitchInlineQueryChosenChat.ts +33 -0
- package/@types/TextQuote.ts +30 -0
- package/@types/TransactionPartner.ts +31 -0
- package/@types/TransactionPartnerAffiliateProgram.ts +24 -0
- package/@types/TransactionPartnerChat.ts +21 -0
- package/@types/TransactionPartnerFragment.ts +18 -0
- package/@types/TransactionPartnerOther.ts +11 -0
- package/@types/TransactionPartnerTelegramAds.ts +11 -0
- package/@types/TransactionPartnerTelegramApi.ts +16 -0
- package/@types/TransactionPartnerUser.ts +70 -0
- package/@types/UniqueGift.ts +38 -0
- package/@types/UniqueGiftBackdrop.ts +23 -0
- package/@types/UniqueGiftBackdropColors.ts +26 -0
- package/@types/UniqueGiftInfo.ts +42 -0
- package/@types/UniqueGiftModel.ts +23 -0
- package/@types/UniqueGiftSymbol.ts +23 -0
- package/@types/Update.ts +177 -0
- package/@types/User.ts +74 -0
- package/@types/UserProfilePhotos.ts +18 -0
- package/@types/UsersShared.ts +19 -0
- package/@types/Venue.ts +48 -0
- package/@types/Video.ts +66 -0
- package/@types/VideoChatEnded.ts +11 -0
- package/@types/VideoChatParticipantsInvited.ts +13 -0
- package/@types/VideoChatScheduled.ts +11 -0
- package/@types/VideoChatStarted.ts +6 -0
- package/@types/VideoNote.ts +39 -0
- package/@types/Voice.ts +34 -0
- package/@types/WebAppData.ts +17 -0
- package/@types/WebAppInfo.ts +11 -0
- package/@types/WebhookInfo.ts +54 -0
- package/@types/WriteAccessAllowed.ts +23 -0
- package/@types/index.ts +395 -0
- package/@types/utils.ts +17 -0
- package/biome.json +58 -0
- package/bun.lock +105 -0
- package/cron/actions-server.ts +87 -0
- package/index.ts +9 -0
- package/nyx-client.ts +133 -0
- package/package.json +22 -0
- package/tsconfig.json +28 -0
- package/types.d.ts +35 -0
- package/utils/actions.ts +30 -0
- package/utils/api.ts +27 -0
- package/utils/enum.ts +5 -0
- package/utils/helpers.ts +71 -0
- package/utils/methods.ts +1943 -0
- package/utils/objects.ts +37 -0
- package/utils/table.ts +72 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// Cron: @reboot
|
|
2
|
+
|
|
3
|
+
import dotenv from "dotenv";
|
|
4
|
+
import { Kysely, MysqlDialect } from "kysely";
|
|
5
|
+
import { createPool } from "mysql2";
|
|
6
|
+
import { createClient } from "redis";
|
|
7
|
+
import z from "zod";
|
|
8
|
+
import type { NyxAction } from "../utils/actions";
|
|
9
|
+
import * as methods from "../utils/methods";
|
|
10
|
+
|
|
11
|
+
const envScheme = z.object({
|
|
12
|
+
BROKER_MYSQL_USER: z.string().nonempty(),
|
|
13
|
+
BROKER_MYSQL_NAME: z.string().nonempty(),
|
|
14
|
+
BROKER_MYSQL_PASS: z.string().nonempty(),
|
|
15
|
+
BROKER_MYSQL_HOST: z.string().nonempty(),
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
const env: z.infer<typeof envScheme> = envScheme.parse(
|
|
19
|
+
dotenv.config({
|
|
20
|
+
path: `${__dirname}/../.env`,
|
|
21
|
+
quiet: true,
|
|
22
|
+
}).parsed,
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
const mysql = createPool({
|
|
26
|
+
user: env.BROKER_MYSQL_USER,
|
|
27
|
+
database: env.BROKER_MYSQL_NAME,
|
|
28
|
+
password: env.BROKER_MYSQL_PASS,
|
|
29
|
+
host: env.BROKER_MYSQL_HOST,
|
|
30
|
+
maxIdle: 2,
|
|
31
|
+
idleTimeout: 120_000,
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const db = new Kysely<{
|
|
35
|
+
actions: {
|
|
36
|
+
id?: number;
|
|
37
|
+
params: NyxAction;
|
|
38
|
+
date: number;
|
|
39
|
+
};
|
|
40
|
+
}>({
|
|
41
|
+
dialect: new MysqlDialect({
|
|
42
|
+
pool: mysql,
|
|
43
|
+
}),
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
const redis = createClient();
|
|
47
|
+
await redis.connect();
|
|
48
|
+
|
|
49
|
+
redis.subscribe("nyx-action", async (input) => {
|
|
50
|
+
try {
|
|
51
|
+
const data: NyxAction = JSON.parse(input);
|
|
52
|
+
|
|
53
|
+
await db
|
|
54
|
+
.insertInto("actions")
|
|
55
|
+
.values({
|
|
56
|
+
params: JSON.stringify(data) as any,
|
|
57
|
+
date: data.date,
|
|
58
|
+
})
|
|
59
|
+
.execute();
|
|
60
|
+
} catch (e) {
|
|
61
|
+
console.error(e);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
setInterval(async () => {
|
|
66
|
+
const tasks = await db
|
|
67
|
+
.selectFrom("actions")
|
|
68
|
+
.selectAll()
|
|
69
|
+
.where("date", "<=", Math.trunc(Date.now() / 1000))
|
|
70
|
+
.execute();
|
|
71
|
+
|
|
72
|
+
if (tasks.length > 0) {
|
|
73
|
+
await db
|
|
74
|
+
.deleteFrom("actions")
|
|
75
|
+
.where("date", "<=", Math.trunc(Date.now() / 1000))
|
|
76
|
+
.execute();
|
|
77
|
+
|
|
78
|
+
for (const task of tasks) {
|
|
79
|
+
const params: NyxAction = JSON.parse(task.params as any);
|
|
80
|
+
|
|
81
|
+
methods[params.type]({
|
|
82
|
+
bot_token: params.bot_token,
|
|
83
|
+
...params.params,
|
|
84
|
+
} as any);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}, 60_000);
|
package/index.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type * from "./@types/index.ts";
|
|
2
|
+
export * from "./nyx-client.ts";
|
|
3
|
+
export type * from "./types.d.ts";
|
|
4
|
+
export * from "./utils/actions.ts";
|
|
5
|
+
export * from "./utils/api.ts";
|
|
6
|
+
export * from "./utils/enum.ts";
|
|
7
|
+
export * from "./utils/helpers.ts";
|
|
8
|
+
export * from "./utils/methods.ts";
|
|
9
|
+
export * from "./utils/table.ts";
|
package/nyx-client.ts
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { createClient } from "redis";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import type { EventTypes } from "./@types";
|
|
4
|
+
import type {
|
|
5
|
+
BotConfig,
|
|
6
|
+
BotInjections,
|
|
7
|
+
BotPipelines,
|
|
8
|
+
SubscribeCallback,
|
|
9
|
+
} from "./types";
|
|
10
|
+
import { NyxResponse } from "./utils/enum";
|
|
11
|
+
import { encodeHTMLEntities } from "./utils/helpers";
|
|
12
|
+
import { sendMessage } from "./utils/methods";
|
|
13
|
+
|
|
14
|
+
type NyxConfig = {
|
|
15
|
+
botConfig: BotConfig;
|
|
16
|
+
pipelines: BotPipelines;
|
|
17
|
+
injections?: BotInjections;
|
|
18
|
+
onStartup?: () => Promise<void>;
|
|
19
|
+
onShutdown?: () => Promise<void>;
|
|
20
|
+
benchmark?: boolean;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
class NyxClient {
|
|
24
|
+
public botConfig: BotConfig | undefined;
|
|
25
|
+
public pipelines: BotPipelines = {};
|
|
26
|
+
public subscriptions: { [key: string]: SubscribeCallback } = {};
|
|
27
|
+
public injections: BotInjections | undefined;
|
|
28
|
+
public benchmark: boolean | undefined;
|
|
29
|
+
|
|
30
|
+
private redis = createClient();
|
|
31
|
+
|
|
32
|
+
public async initialize(config: NyxConfig) {
|
|
33
|
+
this.botConfig = z
|
|
34
|
+
.object({
|
|
35
|
+
username: z.string().nonempty(),
|
|
36
|
+
token: z.string().nonempty(),
|
|
37
|
+
api: z.string().default("https://api.telegram.org"),
|
|
38
|
+
admin_id: z.coerce.number().optional(),
|
|
39
|
+
})
|
|
40
|
+
.parse(config.botConfig);
|
|
41
|
+
this.pipelines = config.pipelines;
|
|
42
|
+
this.injections = config.injections;
|
|
43
|
+
this.benchmark = config.benchmark;
|
|
44
|
+
|
|
45
|
+
await this.redis.connect();
|
|
46
|
+
this.redis.subscribe(
|
|
47
|
+
this.botConfig.username,
|
|
48
|
+
this.handleUpdateRequest.bind(this),
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
config.onStartup?.();
|
|
52
|
+
|
|
53
|
+
process.on("SIGTERM", async () => {
|
|
54
|
+
await config.onShutdown?.();
|
|
55
|
+
process.exit(0);
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
public async handleUpdateRequest(update: string | object) {
|
|
60
|
+
if (this.benchmark) {
|
|
61
|
+
console.time("benchmark-request");
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const inject = await this.injections?.();
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
const data = typeof update === "string" ? JSON.parse(update) : update;
|
|
68
|
+
|
|
69
|
+
if ("update_id" in data) {
|
|
70
|
+
delete data.update_id;
|
|
71
|
+
const update_type: keyof EventTypes = Object.keys(data)[0] as any;
|
|
72
|
+
|
|
73
|
+
if (!this.pipelines[update_type]) return;
|
|
74
|
+
|
|
75
|
+
for (const handler of this.pipelines[update_type]) {
|
|
76
|
+
const result = await handler(data[update_type], inject?.injections);
|
|
77
|
+
|
|
78
|
+
if (result === NyxResponse.Finish) {
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
} else if ("type" in data && "data" in data) {
|
|
83
|
+
for (const type in this.subscriptions) {
|
|
84
|
+
if (data.type === type) {
|
|
85
|
+
this.subscriptions[type]!(data.data);
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
} catch (e: any) {
|
|
91
|
+
console.error(e);
|
|
92
|
+
|
|
93
|
+
if (this.botConfig?.admin_id) {
|
|
94
|
+
sendMessage({
|
|
95
|
+
chat_id: this.botConfig?.admin_id,
|
|
96
|
+
text: `🚫 <b>Error Reporting</b>\n\n<pre>${encodeHTMLEntities(e.stack || e.toString())}</pre>`,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
} finally {
|
|
100
|
+
await inject?.onFinish?.();
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (this.benchmark) {
|
|
104
|
+
console.timeEnd("benchmark-request");
|
|
105
|
+
|
|
106
|
+
console.log(
|
|
107
|
+
"Memory Usage:",
|
|
108
|
+
Object.fromEntries(
|
|
109
|
+
Object.entries(process.memoryUsage()).map(([k, v]) => [
|
|
110
|
+
k,
|
|
111
|
+
`${Math.trunc((v / 1024 / 1024) * 100) / 100}MB`,
|
|
112
|
+
]),
|
|
113
|
+
),
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
console.log("------------------------------");
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
public subscribe(event: string, callback: SubscribeCallback) {
|
|
121
|
+
this.subscriptions[event] = callback;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
public unsubscribe(event: string) {
|
|
125
|
+
if (event in this.subscriptions) {
|
|
126
|
+
delete this.subscriptions[event];
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const client = new NyxClient();
|
|
132
|
+
|
|
133
|
+
export default client;
|
package/package.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "nyx-bot-client",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"module": "index.ts",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"devDependencies": {
|
|
7
|
+
"@types/bun": "latest"
|
|
8
|
+
},
|
|
9
|
+
"peerDependencies": {
|
|
10
|
+
"typescript": "^5"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@biomejs/biome": "^2.2.4",
|
|
14
|
+
"@types/node": "^24.5.2",
|
|
15
|
+
"dotenv": "^17.2.2",
|
|
16
|
+
"kysely": "^0.28.7",
|
|
17
|
+
"mysql2": "^3.15.0",
|
|
18
|
+
"redis": "^5.8.2",
|
|
19
|
+
"ts-debounce": "^4.0.0",
|
|
20
|
+
"zod": "^4.1.9"
|
|
21
|
+
}
|
|
22
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
// Environment setup & latest features
|
|
4
|
+
"lib": ["ESNext"],
|
|
5
|
+
"target": "ESNext",
|
|
6
|
+
"module": "ESNext",
|
|
7
|
+
"moduleDetection": "force",
|
|
8
|
+
"jsx": "react-jsx",
|
|
9
|
+
"allowJs": true,
|
|
10
|
+
|
|
11
|
+
// Bundler mode
|
|
12
|
+
"moduleResolution": "bundler",
|
|
13
|
+
"allowImportingTsExtensions": true,
|
|
14
|
+
"verbatimModuleSyntax": true,
|
|
15
|
+
"noEmit": true,
|
|
16
|
+
|
|
17
|
+
// Best practices
|
|
18
|
+
"strict": true,
|
|
19
|
+
"skipLibCheck": true,
|
|
20
|
+
"noFallthroughCasesInSwitch": true,
|
|
21
|
+
"noUncheckedIndexedAccess": true,
|
|
22
|
+
|
|
23
|
+
// Some stricter flags (disabled by default)
|
|
24
|
+
"noUnusedLocals": false,
|
|
25
|
+
"noUnusedParameters": false,
|
|
26
|
+
"noPropertyAccessFromIndexSignature": false
|
|
27
|
+
}
|
|
28
|
+
}
|
package/types.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { Kysely } from "kysely";
|
|
2
|
+
import type { Connection, Pool } from "mysql2";
|
|
3
|
+
import type { RedisClientType } from "redis";
|
|
4
|
+
import type { EventTypes } from "./@types";
|
|
5
|
+
import type { NyxResponse } from "./utils/enum";
|
|
6
|
+
|
|
7
|
+
export type BotConfig = {
|
|
8
|
+
username: string;
|
|
9
|
+
token: string;
|
|
10
|
+
api?: string;
|
|
11
|
+
admin_id?: number;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export type BotPipeline<K extends keyof EventTypes, T> = (
|
|
15
|
+
data: EventTypes[K],
|
|
16
|
+
injections?: Injections<T>,
|
|
17
|
+
) => Promise<NyxResponse>;
|
|
18
|
+
|
|
19
|
+
export type BotPipelines = {
|
|
20
|
+
[K in keyof EventTypes]?: BotPipeline<K>[];
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export type SubscribeCallback = (params: any) => void;
|
|
24
|
+
|
|
25
|
+
export type BotInjections = () => Promise<{
|
|
26
|
+
injections: Injections;
|
|
27
|
+
onFinish?: () => Promise<void>;
|
|
28
|
+
}>;
|
|
29
|
+
|
|
30
|
+
export type Injections<T> = {
|
|
31
|
+
mysql?: Connection | Pool;
|
|
32
|
+
redis?: RedisClientType;
|
|
33
|
+
db?: Kysely<T>;
|
|
34
|
+
[key: string]: any;
|
|
35
|
+
};
|
package/utils/actions.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { createClient, type RedisClientType } from "redis";
|
|
2
|
+
import type * as methods from "./methods.ts";
|
|
3
|
+
|
|
4
|
+
type MethodName = keyof typeof methods;
|
|
5
|
+
|
|
6
|
+
type ParamsOf<T extends MethodName> = T extends MethodName
|
|
7
|
+
? Parameters<(typeof methods)[T]>[0]
|
|
8
|
+
: never;
|
|
9
|
+
|
|
10
|
+
export type NyxAction<T extends MethodName = MethodName> = {
|
|
11
|
+
type: T;
|
|
12
|
+
params: ParamsOf<T>;
|
|
13
|
+
date: number;
|
|
14
|
+
bot_token: string;
|
|
15
|
+
bot_api_server?: string;
|
|
16
|
+
redis?: RedisClientType;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const actionBroker = async <T extends MethodName>(
|
|
20
|
+
action: NyxAction<T>,
|
|
21
|
+
) => {
|
|
22
|
+
if (action.redis) {
|
|
23
|
+
await action.redis.publish("nyx-action", JSON.stringify(action));
|
|
24
|
+
} else {
|
|
25
|
+
const redis = createClient();
|
|
26
|
+
await redis.connect();
|
|
27
|
+
await redis.publish("nyx-action", JSON.stringify(action));
|
|
28
|
+
await redis.close();
|
|
29
|
+
}
|
|
30
|
+
};
|
package/utils/api.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import client from "../nyx-client";
|
|
2
|
+
|
|
3
|
+
export const requestTelegramAPI = async (
|
|
4
|
+
method: string,
|
|
5
|
+
params: any,
|
|
6
|
+
): Promise<any> => {
|
|
7
|
+
const token = params.bot_token ?? client.botConfig!.token;
|
|
8
|
+
const api =
|
|
9
|
+
params.bot_api_server ??
|
|
10
|
+
client.botConfig?.api ??
|
|
11
|
+
"https://api.telegram.org";
|
|
12
|
+
const request_method = params.request_method ?? "POST";
|
|
13
|
+
|
|
14
|
+
delete params.bot_token;
|
|
15
|
+
delete params.bot_api_server;
|
|
16
|
+
delete params.request_method;
|
|
17
|
+
|
|
18
|
+
const request = await fetch(`${api}/bot${token}/${method}`, {
|
|
19
|
+
method: request_method,
|
|
20
|
+
body: JSON.stringify(params),
|
|
21
|
+
headers: {
|
|
22
|
+
"Content-Type": "application/json",
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
return await request.json();
|
|
27
|
+
};
|
package/utils/enum.ts
ADDED
package/utils/helpers.ts
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getChatMember,
|
|
3
|
+
type getChatMemberParams,
|
|
4
|
+
type methodParams,
|
|
5
|
+
} from "./methods";
|
|
6
|
+
|
|
7
|
+
export const isUserMemberOf = async (params: getChatMemberParams) => {
|
|
8
|
+
const result = await getChatMember(params);
|
|
9
|
+
|
|
10
|
+
if (result.ok) {
|
|
11
|
+
return !["left", "kicked"].includes(result.result.status);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return false;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export const isUserAdminOf = async (params: getChatMemberParams) => {
|
|
18
|
+
const result = await getChatMember(params);
|
|
19
|
+
|
|
20
|
+
if (result.ok) {
|
|
21
|
+
return ["creator", "administrator"].includes(result.result.status);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return false;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export const mentionUserEntity = (text: string, user_id: number) =>
|
|
28
|
+
`<a href='tg://user?id=${user_id}'>${text}</a>`;
|
|
29
|
+
|
|
30
|
+
export type SponsorChat = {
|
|
31
|
+
chat_id: number;
|
|
32
|
+
username?: string;
|
|
33
|
+
title?: string;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export type getRemainingSponsorChatsParams = {
|
|
37
|
+
user_id: number;
|
|
38
|
+
sponsors: SponsorChat[];
|
|
39
|
+
} & methodParams;
|
|
40
|
+
|
|
41
|
+
export const getRemainingSponsorChats = async (
|
|
42
|
+
params: getRemainingSponsorChatsParams,
|
|
43
|
+
) => {
|
|
44
|
+
const result = await Promise.all(
|
|
45
|
+
params.sponsors.map(
|
|
46
|
+
(sponsor) =>
|
|
47
|
+
new Promise<[boolean, SponsorChat]>((resolve) => {
|
|
48
|
+
isUserMemberOf({
|
|
49
|
+
chat_id: sponsor.chat_id,
|
|
50
|
+
user_id: params.user_id,
|
|
51
|
+
bot_api_server: params.bot_api_server,
|
|
52
|
+
bot_token: params.bot_token,
|
|
53
|
+
})
|
|
54
|
+
.then((result) => {
|
|
55
|
+
resolve([result, sponsor]);
|
|
56
|
+
})
|
|
57
|
+
.catch(() => {
|
|
58
|
+
resolve([false, sponsor]);
|
|
59
|
+
});
|
|
60
|
+
}),
|
|
61
|
+
),
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
return result.filter(([joined]) => !joined).map(([, sponsor]) => sponsor);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export const encodeHTMLEntities = (str: string): string => {
|
|
68
|
+
return str.replace(/[\u00A0-\u9999<>&"'`]/g, (char) => {
|
|
69
|
+
return `&#${char.charCodeAt(0)};`;
|
|
70
|
+
});
|
|
71
|
+
};
|