teh-bot 1.0.3 → 1.0.4
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/index.js +105 -35
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -86,8 +86,14 @@ class TelegramBot extends EventEmitter {
|
|
|
86
86
|
})
|
|
87
87
|
|
|
88
88
|
req.on("error", reject)
|
|
89
|
-
if (body instanceof Stream)
|
|
90
|
-
|
|
89
|
+
if (body instanceof Stream) {
|
|
90
|
+
body.pipe(req)
|
|
91
|
+
body.on("end", () => req.end())
|
|
92
|
+
body.on("error", (err) => {
|
|
93
|
+
req.destroy()
|
|
94
|
+
reject(err)
|
|
95
|
+
})
|
|
96
|
+
} else {
|
|
91
97
|
req.write(body)
|
|
92
98
|
req.end()
|
|
93
99
|
}
|
|
@@ -716,54 +722,68 @@ class TelegramBot extends EventEmitter {
|
|
|
716
722
|
}
|
|
717
723
|
|
|
718
724
|
_buildMultipartStream(formData, boundary) {
|
|
719
|
-
const stream = new Readable({
|
|
725
|
+
const stream = new Readable({
|
|
726
|
+
read() {},
|
|
727
|
+
})
|
|
720
728
|
const nl = "\r\n"
|
|
721
729
|
;(async () => {
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
730
|
+
try {
|
|
731
|
+
for (const [key, value] of Object.entries(formData)) {
|
|
732
|
+
if (value === undefined || value === null) continue
|
|
733
|
+
|
|
734
|
+
stream.push(`--${boundary}${nl}`)
|
|
735
|
+
if (value && typeof value === "object" && (value.data || value instanceof Stream || Buffer.isBuffer(value))) {
|
|
736
|
+
const fileData = value.data || value
|
|
737
|
+
const filename = value.filename || `file_${Date.now()}.jpg`
|
|
738
|
+
const contentType = value.contentType || this._getMime(extname(filename)) || "image/jpeg"
|
|
739
|
+
|
|
740
|
+
stream.push(`Content-Disposition: form-data; name="${key}"; filename="${filename}"${nl}`)
|
|
741
|
+
stream.push(`Content-Type: ${contentType}${nl}${nl}`)
|
|
742
|
+
|
|
743
|
+
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
|
+
}
|
|
750
|
+
} else {
|
|
751
|
+
stream.push(fileData)
|
|
752
|
+
}
|
|
733
753
|
} else {
|
|
734
|
-
stream.push(
|
|
754
|
+
stream.push(`Content-Disposition: form-data; name="${key}"${nl}${nl}`)
|
|
755
|
+
stream.push(typeof value === "object" ? JSON.stringify(value) : String(value))
|
|
735
756
|
}
|
|
736
|
-
|
|
737
|
-
stream.push(`Content-Disposition: form-data; name="${key}"${nl}${nl}`)
|
|
738
|
-
stream.push(typeof value === "object" ? JSON.stringify(value) : String(value))
|
|
757
|
+
stream.push(nl)
|
|
739
758
|
}
|
|
740
|
-
stream.push(nl)
|
|
759
|
+
stream.push(`--${boundary}--${nl}`)
|
|
760
|
+
} catch (err) {
|
|
761
|
+
console.error("[v0] Error building multipart stream:", err)
|
|
762
|
+
} finally {
|
|
763
|
+
stream.push(null)
|
|
741
764
|
}
|
|
742
|
-
stream.push(`--${boundary}--${nl}`)
|
|
743
|
-
stream.push(null)
|
|
744
765
|
})()
|
|
745
766
|
|
|
746
767
|
return stream
|
|
747
768
|
}
|
|
748
769
|
|
|
749
770
|
async _prepareFile(source, type) {
|
|
750
|
-
|
|
751
|
-
|
|
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 }
|
|
752
775
|
|
|
753
776
|
if (typeof source === "string") {
|
|
754
777
|
if (source.startsWith("http")) {
|
|
755
|
-
// Fetch remote URL and return as stream
|
|
756
778
|
return new Promise((resolve, reject) => {
|
|
757
|
-
|
|
758
|
-
client
|
|
779
|
+
https
|
|
759
780
|
.get(source, (res) => {
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
}
|
|
781
|
+
const filename = basename(new URL(source).pathname) || `file_${Date.now()}.jpg`
|
|
782
|
+
const contentType = res.headers["content-type"] || defaultMime
|
|
763
783
|
resolve({
|
|
764
784
|
data: res,
|
|
765
|
-
filename:
|
|
766
|
-
contentType:
|
|
785
|
+
filename: filename,
|
|
786
|
+
contentType: contentType,
|
|
767
787
|
})
|
|
768
788
|
})
|
|
769
789
|
.on("error", reject)
|
|
@@ -771,25 +791,34 @@ class TelegramBot extends EventEmitter {
|
|
|
771
791
|
}
|
|
772
792
|
|
|
773
793
|
// Local file
|
|
794
|
+
const filename = basename(source)
|
|
774
795
|
return {
|
|
775
796
|
data: createReadStream(source),
|
|
776
|
-
filename:
|
|
777
|
-
contentType: this._getMime(extname(
|
|
797
|
+
filename: filename,
|
|
798
|
+
contentType: this._getMime(extname(filename)) || defaultMime,
|
|
778
799
|
}
|
|
779
800
|
}
|
|
780
801
|
return source
|
|
781
802
|
}
|
|
782
803
|
|
|
783
|
-
_getMime(
|
|
804
|
+
_getMime(extOrType) {
|
|
784
805
|
const mimes = {
|
|
785
806
|
photo: "image/jpeg",
|
|
807
|
+
image: "image/jpeg",
|
|
786
808
|
video: "video/mp4",
|
|
787
809
|
audio: "audio/mpeg",
|
|
810
|
+
document: "application/octet-stream",
|
|
788
811
|
".jpg": "image/jpeg",
|
|
812
|
+
".jpeg": "image/jpeg",
|
|
789
813
|
".png": "image/png",
|
|
814
|
+
".gif": "image/gif",
|
|
790
815
|
".mp4": "video/mp4",
|
|
816
|
+
".mp3": "audio/mpeg",
|
|
817
|
+
".pdf": "application/pdf",
|
|
818
|
+
".zip": "application/zip",
|
|
791
819
|
}
|
|
792
|
-
|
|
820
|
+
const key = extOrType?.toLowerCase()
|
|
821
|
+
return mimes[key] || (key?.startsWith(".") ? "application/octet-stream" : mimes.photo)
|
|
793
822
|
}
|
|
794
823
|
|
|
795
824
|
_flattenOptions(options) {
|
|
@@ -828,6 +857,47 @@ class TelegramBot extends EventEmitter {
|
|
|
828
857
|
return this.request("getWebhookInfo")
|
|
829
858
|
}
|
|
830
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),
|
|
869
|
+
}
|
|
870
|
+
return this.request(method, {}, formData)
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
async setMyCommands(commands, options = {}) {
|
|
874
|
+
return this.request("setMyCommands", { commands, ...options })
|
|
875
|
+
}
|
|
876
|
+
|
|
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
|
+
}
|
|
888
|
+
|
|
889
|
+
async getUserProfilePhotos(userId, options = {}) {
|
|
890
|
+
return this.request("getUserProfilePhotos", { user_id: userId, ...options })
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
async createChatInviteLink(chatId, options = {}) {
|
|
894
|
+
return this.request("createChatInviteLink", { chat_id: chatId, ...options })
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
async revokeChatInviteLink(chatId, inviteLink) {
|
|
898
|
+
return this.request("revokeChatInviteLink", { chat_id: chatId, invite_link: inviteLink })
|
|
899
|
+
}
|
|
900
|
+
|
|
831
901
|
static InlineKeyboard() {
|
|
832
902
|
return new InlineKeyboardBuilder()
|
|
833
903
|
}
|