@2byte/tgbot-framework 1.0.8 → 1.0.10

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@2byte/tgbot-framework",
3
- "version": "1.0.8",
3
+ "version": "1.0.10",
4
4
  "description": "A TypeScript framework for creating Telegram bots with sections-based architecture (Bun optimized)",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
package/src/core/App.ts CHANGED
@@ -46,7 +46,7 @@ export class App {
46
46
 
47
47
  public bot!: Telegraf<Telegraf2byteContext>;
48
48
  private sectionClasses: Map<string, typeof Section> = new Map();
49
- private runnedSections: WeakMap<UserModel, RunnedSection | Map<string, RunnedSection>> =
49
+ private runnedSections: WeakMap<UserModel, RunnedSection[]> =
50
50
  new WeakMap();
51
51
  private middlewares: CallableFunction[] = [];
52
52
  private apiServiceManager!: ApiServiceManager;
@@ -205,9 +205,9 @@ export class App {
205
205
  middleware();
206
206
  });
207
207
 
208
+ this.registerCommands();
208
209
  this.registerActionForCallbackQuery();
209
210
  this.registerHears();
210
- this.registerCommands();
211
211
  this.registerMessageHandlers();
212
212
  await this.registerServices();
213
213
 
@@ -702,7 +702,7 @@ export class App {
702
702
  this.debugLog(`Register command ${command} for section ${sectionId}`);
703
703
  if (command) {
704
704
  this.bot.command(command, async (ctx: Telegraf2byteContext) => {
705
- const sectionRoute = new RunSectionRoute().section(sectionId).method("index");
705
+ const sectionRoute = new RunSectionRoute().section(sectionId).method("index").runAsCommand();
706
706
  await this.runSection(ctx, sectionRoute);
707
707
  });
708
708
  }
@@ -731,19 +731,23 @@ export class App {
731
731
  throw new Error(`Section ${sectionId} not found at path ${pathSectionModule}.ts`);
732
732
  }
733
733
 
734
- if (freshVersion) {
735
- pathSectionModule += "?update=" + Date.now();
736
- }
737
-
738
- // For bypassing cache in Node.js/Bun, we use file:// protocol with a query parameter
739
- let importPath = pathSectionModule;
740
- if (freshVersion) {
741
- // We convert the path to a file:// URL with a query parameter
742
- const fileUrl = new URL(`file:///${pathSectionModule.replace(/\\/g, "/")}`);
743
- fileUrl.searchParams.set("t", Date.now().toString());
744
- importPath = fileUrl.href;
734
+ // For bypassing cache in Bun, we need to clear the module cache
735
+ if (freshVersion && typeof Bun !== 'undefined') {
736
+ // Clear Bun's module cache for this specific module
737
+ const modulePath = pathSectionModule + ".ts";
738
+ this.debugLog('Clearing cache for fresh version of section:', modulePath);
739
+
740
+ // In Bun, we can use dynamic import with a unique query to bypass cache
741
+ // But we need to resolve the absolute path first
742
+ const absolutePath = path.resolve(modulePath);
743
+
744
+ // Try to delete from require cache if it exists
745
+ if (require.cache && require.cache[absolutePath]) {
746
+ delete require.cache[absolutePath];
747
+ }
745
748
  }
746
- const sectionClass = (await import(importPath)).default as typeof Section;
749
+
750
+ const sectionClass = (await import(pathSectionModule)).default as typeof Section;
747
751
  this.debugLog("Loaded section", sectionId);
748
752
 
749
753
  return sectionClass;
@@ -787,56 +791,74 @@ export class App {
787
791
  }
788
792
  this.debugLog("Using section class:", sectionClass);
789
793
 
790
- const sectionInstance: Section = new sectionClass({
791
- ctx,
792
- bot: this.bot,
793
- app: this,
794
- route: sectionRoute,
795
- } as SectionOptions);
794
+ let sectionInstance: Section | undefined;
795
+
796
+ const createSectionInstance = (sectionClass: typeof Section) => {
797
+ return new sectionClass({
798
+ ctx,
799
+ bot: this.bot,
800
+ app: this,
801
+ route: sectionRoute,
802
+ } as SectionOptions);
803
+ };
804
+
805
+ const createRunnedSection = (instance: Section, route: RunSectionRoute): RunnedSection => {
806
+ return {
807
+ instance,
808
+ route,
809
+ };
810
+ };
811
+
812
+ const findRunnedSection = () => {
813
+ const userRunnedSections = this.runnedSections.get(ctx.user);
814
+ if (userRunnedSections && Array.isArray(userRunnedSections)) {
815
+ return userRunnedSections.find((section) => section.route.getSection() === sectionId);
816
+ }
817
+ return undefined;
818
+ };
796
819
 
797
- let runnedSection;
798
- let userRunnedSections: Map<string, RunnedSection> | RunnedSection | undefined;
799
- let sectionInstalled = false;
820
+ let isRestoredSection = false;
821
+ let runnedSection : RunnedSection | undefined = undefined;
822
+ let createdNewSectionInstance = false;
800
823
 
801
824
  if (this.config.keepSectionInstances) {
802
- userRunnedSections = this.runnedSections.get(ctx.user);
803
- if (userRunnedSections instanceof Map) {
804
- runnedSection &&= userRunnedSections.get(sectionId);
825
+ runnedSection = findRunnedSection();
826
+ if (runnedSection) {
827
+ runnedSection.instance
828
+ .updateCtx(ctx);
829
+
830
+ if (sectionRoute.runIsCallbackQuery) {
831
+ runnedSection.route.runAsCallbackQuery();
832
+ }
833
+
834
+ isRestoredSection = true;
835
+ } else {
836
+ createdNewSectionInstance = true;
805
837
  }
806
838
  } else {
807
- runnedSection &&= this.runnedSections.get(ctx.user);
839
+ createdNewSectionInstance = true;
808
840
  }
809
- if (runnedSection) {
810
- this.debugLog(`Restored a runned section for user ${ctx.user.username}:`, runnedSection);
841
+
842
+ if (isRestoredSection) {
843
+ this.debugLog(`Restored a runned section for user ${ctx.user.username}:`, runnedSection?.instance.sectionId);
811
844
  }
812
845
 
813
- if (!runnedSection && this.config.keepSectionInstances) {
814
- if (userRunnedSections instanceof Map) {
815
- userRunnedSections.set(sectionId, {
816
- instance: sectionInstance,
817
- route: sectionRoute,
818
- });
819
- sectionInstalled = true;
820
- } else if (userRunnedSections === undefined) {
821
- userRunnedSections = new Map<string, RunnedSection>([
822
- [
823
- sectionId,
824
- {
825
- instance: sectionInstance,
826
- route: sectionRoute,
827
- },
828
- ],
829
- ]);
830
- sectionInstalled = true;
846
+ if (createdNewSectionInstance) {
847
+ this.debugLog(`Creating new section instance for user ${ctx.user.username}`);
848
+ runnedSection = createRunnedSection(createSectionInstance(sectionClass), sectionRoute);
849
+
850
+ if (this.config.keepSectionInstances) {
851
+ if (!this.runnedSections.has(ctx.user)) {
852
+ this.runnedSections.set(ctx.user, []);
853
+ }
854
+ (this.runnedSections.get(ctx.user) as RunnedSection[]).push(runnedSection);
831
855
  }
832
856
  }
833
857
 
834
- if (!runnedSection && !this.config.keepSectionInstances) {
835
- this.runnedSections.set(ctx.user, {
836
- instance: sectionInstance,
837
- route: sectionRoute,
838
- });
839
- sectionInstalled = true;
858
+ if (runnedSection) {
859
+ sectionInstance = runnedSection.instance;
860
+ } else {
861
+ throw new Error(`Failed to create or retrieve runned section for ${sectionId}`);
840
862
  }
841
863
 
842
864
  if (!(sectionInstance as any)[method]) {
@@ -858,14 +880,12 @@ export class App {
858
880
  const unsetupMethod = sectionInstance.unsetup;
859
881
 
860
882
  // Run setup if section is installed
861
- if (sectionInstalled && setupMethod && typeof setupMethod === "function") {
862
- if (sectionInstalled) {
883
+ if (createdNewSectionInstance && setupMethod && typeof setupMethod === "function") {
863
884
  this.debugLog(`[Setup] Section ${sectionId} install for user ${ctx.user.username}`);
864
885
  await sectionInstance.setup();
865
886
  this.debugLog(
866
887
  `[Setup finish] Section ${sectionId} installed for user ${ctx.user.username}`
867
888
  );
868
- }
869
889
  }
870
890
 
871
891
  // Run up method
@@ -46,9 +46,9 @@ export class Artisan {
46
46
  * Возвращает шаблон для новой секции
47
47
  */
48
48
  private getSectionTemplate(name: string): string {
49
- return `import { Section } from "../../src/illumination/Section";
50
- import { SectionOptions } from "../../src/types";
51
- import { InlineKeyboard } from "../../src/illumination/InlineKeyboard";
49
+ return `import { Section } from "@2byte/tgbot-framework";
50
+ import { SectionOptions } from "@2byte/tgbot-framework";
51
+ import { InlineKeyboard } from "@2byte/tgbot-framework";
52
52
 
53
53
  export default class ${name}Section extends Section {
54
54
  static command = "${name.toLowerCase()}";
@@ -213,13 +213,13 @@ export default class Message2byte {
213
213
  const editedText = this.editMessageText(this.messageValue, this.messageExtra);
214
214
 
215
215
  if (editedText && 'message_id' in editedText) {
216
- this.messageId = editedText.message_id as number;
216
+ // this.messageId = editedText.message_id as number;
217
217
  }
218
218
 
219
219
  return editedText;
220
220
  }
221
221
  } else {
222
- this.messageExtra.message_id = this.messageId;
222
+ // this.messageExtra.message_id = this.messageId;
223
223
 
224
224
  const messageEntity = await this.editMessageText(this.messageValue, this.messageExtra);
225
225
 
@@ -237,7 +237,7 @@ export default class Message2byte {
237
237
 
238
238
  const replyEntity = this.ctx.reply(this.messageValue, this.messageExtra);
239
239
 
240
- this.messageId = (await replyEntity).message_id;
240
+ // this.messageId = (await replyEntity).message_id;
241
241
 
242
242
  return replyEntity;
243
243
  }
@@ -1,6 +1,7 @@
1
1
  import type { Section, Telegraf2byteContext } from "@2byte/tgbot-framework";
2
2
  import Message2byte from "./Message2Byte";
3
3
  import Message2ByteLiveProgressive from "./Message2ByteLiveProgressive";
4
+ import { InlineKeyboard } from "./InlineKeyboard";
4
5
 
5
6
  export default class Message2bytePool {
6
7
  private message2byte: Message2byte;
@@ -61,6 +62,11 @@ export default class Message2bytePool {
61
62
  return Message2ByteLiveProgressive.init(this.message2byte, this);
62
63
  }
63
64
 
65
+ inlineKeyboard(keyboard: InlineKeyboard): this {
66
+ this.message2byte.inlineKeyboard(keyboard);
67
+ return this;
68
+ }
69
+
64
70
  async send() {
65
71
 
66
72
  const entity = await this.message2byte.send();
@@ -47,6 +47,16 @@ export class RunSectionRoute {
47
47
  return this;
48
48
  }
49
49
 
50
+ runAsCommand(): this {
51
+ this.runParams.runAsCallcackQuery = false;
52
+ return this;
53
+ }
54
+
55
+ runAsCallbackQuery(): this {
56
+ this.runParams.runAsCallcackQuery = true;
57
+ return this;
58
+ }
59
+
50
60
  getMethod(): string | null {
51
61
  return this.runParams.method;
52
62
  }
@@ -310,7 +310,7 @@ export class Section {
310
310
  return false;
311
311
  }
312
312
 
313
- backInlineButtion(data: string): any {
313
+ backInlineButton(data: string): any {
314
314
  return this.markup.button.callback(this.labelBack, data);
315
315
  }
316
316
 
@@ -396,6 +396,16 @@ export class Section {
396
396
  : this.createPoolNewMessage(message);
397
397
  }
398
398
 
399
+ updateCtx(newCtx: Telegraf2byteContext): this {
400
+ this.ctx = newCtx;
401
+ return this;
402
+ }
403
+
404
+ updateRoute(newRoute: RunSectionRoute): this {
405
+ this.route = newRoute;
406
+ return this;
407
+ }
408
+
399
409
  getCtx(): Telegraf2byteContext {
400
410
  return this.ctx;
401
411
  }
@@ -1,7 +1,8 @@
1
1
  import type { Database } from "bun:sqlite";
2
2
  import { MakeManualPaginateButtonsParams, ModelPaginateParams, PaginateResult } from "@2byte/tgbot-framework";
3
3
  import { Section } from "@2byte/tgbot-framework";
4
+ import { Model as BaseModel } from "@2byte/tgbot-framework";
4
5
 
5
- export abstract class Model {
6
+ export abstract class Model extends BaseModel {
6
7
 
7
8
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "{{kebabName}}",
3
- "version": "1.0.8",
3
+ "version": "1.0.0",
4
4
  "description": "{{description}}",
5
5
  "main": "bot.ts",
6
6
  "scripts": {
@@ -21,7 +21,7 @@
21
21
  "author": "{{author}}",
22
22
  "license": "MIT",
23
23
  "dependencies": {
24
- "@2byte/tgbot-framework": "^1.0.6"
24
+ "@2byte/tgbot-framework": "^1.0.10"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@types/node": "^20.19.8",