teh-bot 1.0.4 → 1.0.6

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.
@@ -65,7 +65,7 @@ class TelegramBot extends EventEmitter {
65
65
  method: "POST",
66
66
  headers: {
67
67
  ...headers,
68
- "User-Agent": "TehBot/1.0.0 (Modern; High-Performance)",
68
+ "User-Agent": "TehBot/1.0.5 (Modern; High-Performance)",
69
69
  },
70
70
  timeout: this.options.requestTimeout,
71
71
  }
@@ -100,8 +100,32 @@ class TelegramBot extends EventEmitter {
100
100
  })
101
101
  }
102
102
 
103
+ async getMe() {
104
+ return this.request("getMe")
105
+ }
106
+
107
+ async getUpdates(params = {}) {
108
+ return this.request("getUpdates", {
109
+ offset: this.offset,
110
+ timeout: this.options.pollingTimeout,
111
+ allowed_updates: this.options.allowedUpdates,
112
+ ...params,
113
+ })
114
+ }
115
+
116
+ async setWebhook(url, params = {}) {
117
+ return this.request("setWebhook", { url, ...params })
118
+ }
119
+
120
+ async deleteWebhook(params = {}) {
121
+ return this.request("deleteWebhook", params)
122
+ }
123
+
124
+ async getWebhookInfo() {
125
+ return this.request("getWebhookInfo")
126
+ }
127
+
103
128
  async sendMessage(chatId, content, options = {}) {
104
- // content can be string (text) or object { image: ..., caption: ... }
105
129
  if (typeof content === "string") {
106
130
  return this.request("sendMessage", { chat_id: chatId, text: content, ...options })
107
131
  }
@@ -607,7 +631,6 @@ class TelegramBot extends EventEmitter {
607
631
  _createContext(update) {
608
632
  const message = update.message || update.edited_message || update.channel_post || update.callback_query?.message
609
633
 
610
- // Fallback logic for chat extraction from various update types
611
634
  const chat =
612
635
  update.message?.chat ||
613
636
  update.callback_query?.message?.chat ||
@@ -642,7 +665,6 @@ class TelegramBot extends EventEmitter {
642
665
  chatMember: update.chat_member,
643
666
  }
644
667
 
645
- // Baileys-style simplified response
646
668
  ctx.send = (content, opts) => {
647
669
  const chatId =
648
670
  ctx.chat?.id ||
@@ -652,7 +674,7 @@ class TelegramBot extends EventEmitter {
652
674
  from?.id
653
675
 
654
676
  if (!chatId) {
655
- console.error("[v0] Context update without valid chatId destination:", JSON.stringify(update))
677
+ console.error("[Teh] Context update without valid chatId destination:", JSON.stringify(update))
656
678
  throw new Error("[Teh] Cannot send message: chat_id could not be resolved from this update context")
657
679
  }
658
680
  return this.sendMessage(chatId, content, opts)
@@ -669,13 +691,11 @@ class TelegramBot extends EventEmitter {
669
691
  })
670
692
  }
671
693
 
672
- // Context helpers for media
673
694
  ctx.replyWithPhoto = (photo, opts) => ctx.send({ image: photo, ...opts })
674
695
  ctx.replyWithVideo = (video, opts) => ctx.send({ video, ...opts })
675
696
  ctx.replyWithAudio = (audio, opts) => ctx.send({ audio, ...opts })
676
697
  ctx.replyWithDocument = (doc, opts) => ctx.send({ document: doc, ...opts })
677
698
 
678
- // Helper methods for callback queries
679
699
  ctx.answerCallbackQuery = (options = {}) => {
680
700
  if (!ctx.callbackQuery?.id) return Promise.resolve(false)
681
701
  return this.answerCallbackQuery(ctx.callbackQuery.id, options)
@@ -683,7 +703,6 @@ class TelegramBot extends EventEmitter {
683
703
 
684
704
  ctx.editMessageText = (text, options = {}) => {
685
705
  if (!ctx.callbackQuery?.message) {
686
- // If it's an inline message (no message object), we need the inline_message_id
687
706
  if (ctx.callbackQuery?.inline_message_id) {
688
707
  return this.editMessageText(text, {
689
708
  inline_message_id: ctx.callbackQuery.inline_message_id,
@@ -741,163 +760,86 @@ class TelegramBot extends EventEmitter {
741
760
  stream.push(`Content-Type: ${contentType}${nl}${nl}`)
742
761
 
743
762
  if (fileData instanceof Stream) {
744
- for await (const chunk of fileData) {
745
- const canPush = stream.push(chunk)
746
- if (!canPush) {
747
- await new Promise((resolve) => stream.once("drain", resolve))
748
- }
749
- }
763
+ fileData.pipe(stream, { end: false })
764
+ await new Promise((resolve, reject) => {
765
+ fileData.on("end", resolve)
766
+ fileData.on("error", reject)
767
+ })
750
768
  } else {
751
769
  stream.push(fileData)
752
770
  }
753
771
  } else {
754
772
  stream.push(`Content-Disposition: form-data; name="${key}"${nl}${nl}`)
755
- stream.push(typeof value === "object" ? JSON.stringify(value) : String(value))
773
+ stream.push(String(value))
756
774
  }
757
- stream.push(nl)
775
+ stream.push(`${nl}`)
758
776
  }
759
777
  stream.push(`--${boundary}--${nl}`)
760
- } catch (err) {
761
- console.error("[v0] Error building multipart stream:", err)
762
- } finally {
763
778
  stream.push(null)
779
+ } catch (err) {
780
+ stream.destroy(err)
764
781
  }
765
782
  })()
766
-
767
783
  return stream
768
784
  }
769
785
 
770
- async _prepareFile(source, type) {
771
- const defaultMime = this._getMime(type) || "image/jpeg"
772
-
773
- if (source instanceof Stream) return { data: source, contentType: defaultMime }
774
- if (Buffer.isBuffer(source)) return { data: source, contentType: defaultMime }
775
-
776
- if (typeof source === "string") {
777
- if (source.startsWith("http")) {
778
- return new Promise((resolve, reject) => {
779
- https
780
- .get(source, (res) => {
781
- const filename = basename(new URL(source).pathname) || `file_${Date.now()}.jpg`
782
- const contentType = res.headers["content-type"] || defaultMime
783
- resolve({
784
- data: res,
785
- filename: filename,
786
- contentType: contentType,
787
- })
788
- })
789
- .on("error", reject)
790
- })
791
- }
792
-
793
- // Local file
794
- const filename = basename(source)
795
- return {
796
- data: createReadStream(source),
797
- filename: filename,
798
- contentType: this._getMime(extname(filename)) || defaultMime,
799
- }
800
- }
801
- return source
802
- }
803
-
804
- _getMime(extOrType) {
805
- const mimes = {
806
- photo: "image/jpeg",
807
- image: "image/jpeg",
808
- video: "video/mp4",
809
- audio: "audio/mpeg",
810
- document: "application/octet-stream",
786
+ _getMime(ext) {
787
+ const mimeTypes = {
811
788
  ".jpg": "image/jpeg",
812
789
  ".jpeg": "image/jpeg",
813
790
  ".png": "image/png",
814
791
  ".gif": "image/gif",
815
792
  ".mp4": "video/mp4",
793
+ ".avi": "video/x-msvideo",
794
+ ".webm": "video/webm",
816
795
  ".mp3": "audio/mpeg",
796
+ ".ogg": "audio/ogg",
797
+ ".wav": "audio/wav",
817
798
  ".pdf": "application/pdf",
818
- ".zip": "application/zip",
799
+ ".doc": "application/msword",
800
+ ".txt": "text/plain",
819
801
  }
820
- const key = extOrType?.toLowerCase()
821
- return mimes[key] || (key?.startsWith(".") ? "application/octet-stream" : mimes.photo)
802
+ return mimeTypes[ext.toLowerCase()] || "application/octet-stream"
822
803
  }
823
804
 
824
- _flattenOptions(options) {
825
- const flat = {}
826
- for (const [key, value] of Object.entries(options)) {
827
- if (typeof value === "object" && value !== null) {
828
- flat[key] = JSON.stringify(value)
829
- } else {
830
- flat[key] = value
805
+ async _prepareFile(source, type) {
806
+ if (typeof source === "string") {
807
+ if (source.startsWith("http://") || source.startsWith("https://")) {
808
+ return source
831
809
  }
832
- }
833
- return flat
834
- }
835
810
 
836
- _formatError(resp) {
837
- const err = new Error(resp.description || "Unknown Telegram Error")
838
- err.code = resp.error_code
839
- err.parameters = resp.parameters
840
- err.response = resp
841
- err.name = "TelegramAPIError"
842
- return err
843
- }
844
-
845
- async deleteWebhook(options = {}) {
846
- return this.request("deleteWebhook", options)
847
- }
848
-
849
- async setWebhook(url, options = {}) {
850
- return this.request("setWebhook", {
851
- url,
852
- ...options,
853
- })
854
- }
855
-
856
- async getWebhookInfo() {
857
- return this.request("getWebhookInfo")
858
- }
859
-
860
- async getMe() {
861
- return this.request("getMe")
862
- }
863
-
864
- async _sendFile(method, chatId, source, type, options = {}) {
865
- const formData = {
866
- chat_id: chatId,
867
- [type]: await this._prepareFile(source, type),
868
- ...this._flattenOptions(options),
811
+ try {
812
+ const stat = statSync(source)
813
+ if (stat.isFile()) {
814
+ return {
815
+ data: createReadStream(source),
816
+ filename: basename(source),
817
+ contentType: this._getMime(extname(source)),
818
+ }
819
+ }
820
+ } catch (e) {
821
+ return source
822
+ }
869
823
  }
870
- return this.request(method, {}, formData)
871
- }
872
-
873
- async setMyCommands(commands, options = {}) {
874
- return this.request("setMyCommands", { commands, ...options })
875
- }
876
824
 
877
- async getMyCommands(options = {}) {
878
- return this.request("getMyCommands", options)
879
- }
880
-
881
- async setChatMenuButton(options = {}) {
882
- return this.request("setChatMenuButton", options)
883
- }
884
-
885
- async getChatMenuButton(options = {}) {
886
- return this.request("getChatMenuButton", options)
887
- }
825
+ if (Buffer.isBuffer(source) || source instanceof Stream) {
826
+ return {
827
+ data: source,
828
+ filename: `file_${Date.now()}.jpg`,
829
+ contentType: "image/jpeg",
830
+ }
831
+ }
888
832
 
889
- async getUserProfilePhotos(userId, options = {}) {
890
- return this.request("getUserProfilePhotos", { user_id: userId, ...options })
833
+ return source
891
834
  }
892
835
 
893
- async createChatInviteLink(chatId, options = {}) {
894
- return this.request("createChatInviteLink", { chat_id: chatId, ...options })
836
+ _formatError(response) {
837
+ const error = new Error(response.description || "Telegram API Error")
838
+ error.response = response
839
+ error.errorCode = response.error_code
840
+ return error
895
841
  }
896
842
 
897
- async revokeChatInviteLink(chatId, inviteLink) {
898
- return this.request("revokeChatInviteLink", { chat_id: chatId, invite_link: inviteLink })
899
- }
900
-
901
843
  static InlineKeyboard() {
902
844
  return new InlineKeyboardBuilder()
903
845
  }
@@ -906,25 +848,22 @@ class TelegramBot extends EventEmitter {
906
848
  return new ReplyKeyboardBuilder()
907
849
  }
908
850
 
909
- static RemoveKeyboard(selective = false) {
910
- return { remove_keyboard: true, selective }
851
+ static RemoveKeyboard() {
852
+ return { remove_keyboard: true }
911
853
  }
912
854
 
913
- static ForceReply(selective = false, placeholder = "") {
914
- const obj = { force_reply: true, selective }
915
- if (placeholder) obj.input_field_placeholder = placeholder
916
- return obj
855
+ static ForceReply() {
856
+ return { force_reply: true }
917
857
  }
918
858
  }
919
859
 
920
860
  class InlineKeyboardBuilder {
921
861
  constructor() {
922
- this.keyboard = []
923
- this.currentRow = []
862
+ this.keyboard = [[]]
924
863
  }
925
864
 
926
865
  text(text, callbackData) {
927
- this.currentRow.push({
866
+ this.keyboard[this.keyboard.length - 1].push({
928
867
  text,
929
868
  callback_data: callbackData,
930
869
  })
@@ -932,7 +871,7 @@ class InlineKeyboardBuilder {
932
871
  }
933
872
 
934
873
  url(text, url) {
935
- this.currentRow.push({
874
+ this.keyboard[this.keyboard.length - 1].push({
936
875
  text,
937
876
  url,
938
877
  })
@@ -940,7 +879,7 @@ class InlineKeyboardBuilder {
940
879
  }
941
880
 
942
881
  login(text, loginUrl) {
943
- this.currentRow.push({
882
+ this.keyboard[this.keyboard.length - 1].push({
944
883
  text,
945
884
  login_url: loginUrl,
946
885
  })
@@ -948,7 +887,7 @@ class InlineKeyboardBuilder {
948
887
  }
949
888
 
950
889
  switchInline(text, query = "") {
951
- this.currentRow.push({
890
+ this.keyboard[this.keyboard.length - 1].push({
952
891
  text,
953
892
  switch_inline_query: query,
954
893
  })
@@ -956,7 +895,7 @@ class InlineKeyboardBuilder {
956
895
  }
957
896
 
958
897
  switchInlineCurrent(text, query = "") {
959
- this.currentRow.push({
898
+ this.keyboard[this.keyboard.length - 1].push({
960
899
  text,
961
900
  switch_inline_query_current_chat: query,
962
901
  })
@@ -964,7 +903,7 @@ class InlineKeyboardBuilder {
964
903
  }
965
904
 
966
905
  game(text) {
967
- this.currentRow.push({
906
+ this.keyboard[this.keyboard.length - 1].push({
968
907
  text,
969
908
  callback_game: {},
970
909
  })
@@ -972,7 +911,7 @@ class InlineKeyboardBuilder {
972
911
  }
973
912
 
974
913
  pay(text) {
975
- this.currentRow.push({
914
+ this.keyboard[this.keyboard.length - 1].push({
976
915
  text,
977
916
  pay: true,
978
917
  })
@@ -980,35 +919,28 @@ class InlineKeyboardBuilder {
980
919
  }
981
920
 
982
921
  row() {
983
- if (this.currentRow.length > 0) {
984
- this.keyboard.push([...this.currentRow])
985
- this.currentRow = []
986
- }
922
+ this.keyboard.push([])
987
923
  return this
988
924
  }
989
925
 
990
926
  build() {
991
- this.row()
992
- return {
993
- inline_keyboard: this.keyboard,
994
- }
927
+ return { inline_keyboard: this.keyboard }
995
928
  }
996
929
  }
997
930
 
998
931
  class ReplyKeyboardBuilder {
999
932
  constructor() {
1000
- this.keyboard = []
1001
- this.currentRow = []
933
+ this.keyboard = [[]]
1002
934
  this.options = {}
1003
935
  }
1004
936
 
1005
937
  text(text) {
1006
- this.currentRow.push({ text })
938
+ this.keyboard[this.keyboard.length - 1].push({ text })
1007
939
  return this
1008
940
  }
1009
941
 
1010
942
  requestContact(text) {
1011
- this.currentRow.push({
943
+ this.keyboard[this.keyboard.length - 1].push({
1012
944
  text,
1013
945
  request_contact: true,
1014
946
  })
@@ -1016,15 +948,15 @@ class ReplyKeyboardBuilder {
1016
948
  }
1017
949
 
1018
950
  requestLocation(text) {
1019
- this.currentRow.push({
951
+ this.keyboard[this.keyboard.length - 1].push({
1020
952
  text,
1021
953
  request_location: true,
1022
954
  })
1023
955
  return this
1024
956
  }
1025
957
 
1026
- requestPoll(text, type) {
1027
- this.currentRow.push({
958
+ requestPoll(text, type = "quiz") {
959
+ this.keyboard[this.keyboard.length - 1].push({
1028
960
  text,
1029
961
  request_poll: { type },
1030
962
  })
@@ -1032,10 +964,7 @@ class ReplyKeyboardBuilder {
1032
964
  }
1033
965
 
1034
966
  row() {
1035
- if (this.currentRow.length > 0) {
1036
- this.keyboard.push([...this.currentRow])
1037
- this.currentRow = []
1038
- }
967
+ this.keyboard.push([])
1039
968
  return this
1040
969
  }
1041
970
 
@@ -1060,7 +989,6 @@ class ReplyKeyboardBuilder {
1060
989
  }
1061
990
 
1062
991
  build() {
1063
- this.row()
1064
992
  return {
1065
993
  keyboard: this.keyboard,
1066
994
  ...this.options,