rc76 wrote: ↑28 Feb 2022, 05:46
(1) How to structure the ahk query for sendMediaGroup
https://core.telegram.org/bots/api#sendmediagroup
I have been using sendMessage, sendPhoto, and they are working great. But when there are many screenshots I wish to send, then they become ugly (it will simply flood the chatroom). So an example of how to use sendMediaGroup will be super helpful and make the delivery of related screenshots much cleaner to read/reference.
Okay, let's start with the
sendMediaGroup method "to send a group of photos, videos, documents or audios as an album". Since you are mainly sending images, as far as I understand, let's focus on sending groups of images/screenshots/photos. Grouping other media types will hopefully work similarly (not tested).
The required
media parameter needs to be an
Array of InputMediaAudio, InputMediaDocument, InputMediaPhoto and InputMediaVideo[...]
[...]
A JSON-serialized array describing messages to be sent, must include 2-10 items
An array... so I expect a structure similar to this:
[ { } , { } , { } ] - with each
{ } part holding the necessary data for a single image.
(It looks like even a single item works, contrary to the description, but then you could use the simpler
SendPhoto method.)
Now let's look at the
InputMediaPhoto type ("Represents a photo to be sent."). Mandatory parameters are:
Code: Select all
type String Type of the result, must be photo
media String File to send.
Pass a file_id to send a file that exists on the Telegram servers (recommended),
pass an HTTP URL for Telegram to get a file from the Internet,
or pass “attach://<file_attach_name>” to upload a new one using multipart/form-data under <file_attach_name> name.
More info on Sending Files »
type is no problem; I (successfully) tried all three approaches mentioned for
media:
1. Using URLs:
Code: Select all
botToken := "" ; add your Telegram bot token
chat_id := ; add your ID
media = ; use URLs
(
[ {"type" : "photo", "media" : "https://www.autohotkey.com/logos/ahk_logo-winter.png", "caption" : "Hello AHK"}
, {"type" : "photo", "media" : "https://www.autohotkey.com/logos/ahk_logo-stpat2.png"}
, {"type" : "photo", "media" : "https://www.autohotkey.com/logos/ahk_logo.png"} ]
)
; sendMediaGroup https://core.telegram.org/bots/api#sendmediagroup
param := "chat_id=" chat_id "&media=" media
str := "https://api.telegram.org/bot" botToken "/sendMediaGroup?"
msgbox % response := url_tovar(str, param)
;---------------------------------------------------------------------------------------
url_tovar(URL, param) {
WebRequest := ComObjCreate("WinHttp.WinHttpRequest.5.1")
WebRequest.Open("POST", URL)
WebRequest.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded")
WebRequest.Send(param)
res := WebRequest.ResponseText
return res
}
2. When you upload a picture to Telegram via URL or from your computer, you'll get
file_ids in the response texts for each picture which you can reuse:
Code: Select all
media =
(
[ {"type" : "photo", "media" : "some file_id of an already used picture", "caption" : "via file_id"} ]
)
3. Now, the last method - uploading pictures from a computer - was kind of a head-scratcher:
or pass “attach://<file_attach_name>” to upload a new one using multipart/form-data under <file_attach_name> name
Seemed at first a bit different than the
multipart upload of the SendPhoto method. But finally, the contents of the error messages and googling around led me to structure the call like this:
Code: Select all
media =
(
[ {"type" : "photo", "media" : "attach://photo_1"}
, {"type" : "photo", "media" : "attach://photo_2"} ]
)
url_str := "https://api.telegram.org/bot" botToken "/sendMediaGroup?media=" media ; ?caption=" caption
objParam := { "chat_id" : chat_id
, "photo_1" : ["202013.jpg"]
, "photo_2" : ["202012.jpg"]}
msgbox % UploadFormData(url_str, objParam)
ExitApp
;---------------------------------------------
UploadFormData(url_str, objParam) ; Upload multipart/form-data
{
CreateFormData(postData, hdr_ContentType, objParam)
whr := ComObjCreate("WinHttp.WinHttpRequest.5.1")
whr.Open("POST", url_str, true)
whr.SetRequestHeader("Content-Type", hdr_ContentType)
; whr.SetRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko") ; ???????
whr.Option(6) := False ; No auto redirect
whr.Send(postData)
whr.WaitForResponse()
json_resp := whr.ResponseText
whr := ; free COM object
return json_resp ; will return a JSON string that contains, among many other things, the file_id of the uploaded file
}
;###################################################################################################################
; by tmplinshi https://www.autohotkey.com/boards/viewtopic.php?f=6&t=7647
/*
CreateFormData - Creates "multipart/form-data" for http post
Usage: CreateFormData(ByRef retData, ByRef retHeader, objParam)
retData - (out) Data used for HTTP POST.
retHeader - (out) Content-Type header used for HTTP POST.
objParam - (in) An object defines the form parameters.
To specify files, use array as the value. Example:
objParam := { "key1": "value1"
, "upload[]": ["1.png", "2.png"] }
Requirement: BinArr.ahk -- https://gist.github.com/tmplinshi/a97d9a99b9aa5a65fd20
Version : 1.20 / 2016-6-17 - Added CreateFormData_WinInet(), which can be used for VxE's HTTPRequest().
1.10 / 2015-6-23 - Fixed a bug
1.00 / 2015-5-14
*/
; Used for WinHttp.WinHttpRequest.5.1, Msxml2.XMLHTTP ...
CreateFormData(ByRef retData, ByRef retHeader, objParam) {
New CreateFormData(retData, retHeader, objParam)
}
; Used for WinInet
CreateFormData_WinInet(ByRef retData, ByRef retHeader, objParam) {
New CreateFormData(safeArr, retHeader, objParam)
size := safeArr.MaxIndex() + 1
VarSetCapacity(retData, size, 1)
DllCall("oleaut32\SafeArrayAccessData", "ptr", ComObjValue(safeArr), "ptr*", pdata)
DllCall("RtlMoveMemory", "ptr", &retData, "ptr", pdata, "ptr", size)
DllCall("oleaut32\SafeArrayUnaccessData", "ptr", ComObjValue(safeArr))
}
Class CreateFormData {
__New(ByRef retData, ByRef retHeader, objParam) {
CRLF := "`r`n"
Boundary := this.RandomBoundary()
BoundaryLine := "------------------------------" . Boundary
; Loop input paramters
binArrs := []
For k, v in objParam
{
If IsObject(v) {
For i, FileName in v
{
str := BoundaryLine . CRLF
. "Content-Disposition: form-data; name=""" . k . """; filename=""" . FileName . """" . CRLF
. "Content-Type: " . this.MimeType(FileName) . CRLF . CRLF
binArrs.Push( BinArr_FromString(str) )
binArrs.Push( BinArr_FromFile(FileName) )
binArrs.Push( BinArr_FromString(CRLF) )
}
} Else {
str := BoundaryLine . CRLF
. "Content-Disposition: form-data; name=""" . k """" . CRLF . CRLF
. v . CRLF
binArrs.Push( BinArr_FromString(str) )
}
}
str := BoundaryLine . "--" . CRLF
binArrs.Push( BinArr_FromString(str) )
retData := BinArr_Join(binArrs*)
retHeader := "multipart/form-data; boundary=----------------------------" . Boundary
}
RandomBoundary() {
str := "0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z"
Sort, str, D| Random
str := StrReplace(str, "|")
Return SubStr(str, 1, 12)
}
MimeType(FileName) {
n := FileOpen(FileName, "r").ReadUInt()
Return (n = 0x474E5089) ? "image/png"
: (n = 0x38464947) ? "image/gif"
: (n&0xFFFF = 0x4D42 ) ? "image/bmp"
: (n&0xFFFF = 0xD8FF ) ? "image/jpeg"
: (n&0xFFFF = 0x4949 ) ? "image/tiff"
: (n&0xFFFF = 0x4D4D ) ? "image/tiff"
: "application/octet-stream"
}
}
;#############################################################################################################
; Update: 2015-6-4 - Added BinArr_ToFile()
BinArr_FromString(str) {
oADO := ComObjCreate("ADODB.Stream")
oADO.Type := 2 ; adTypeText
oADO.Mode := 3 ; adModeReadWrite
oADO.Open
oADO.Charset := "UTF-8"
oADO.WriteText(str)
oADO.Position := 0
oADO.Type := 1 ; adTypeBinary
oADO.Position := 3 ; Skip UTF-8 BOM
return oADO.Read, oADO.Close
}
BinArr_FromFile(FileName) {
oADO := ComObjCreate("ADODB.Stream")
oADO.Type := 1 ; adTypeBinary
oADO.Open
oADO.LoadFromFile(FileName)
return oADO.Read, oADO.Close
}
BinArr_Join(Arrays*) {
oADO := ComObjCreate("ADODB.Stream")
oADO.Type := 1 ; adTypeBinary
oADO.Mode := 3 ; adModeReadWrite
oADO.Open
For i, arr in Arrays
oADO.Write(arr)
oADO.Position := 0
return oADO.Read, oADO.Close
}
BinArr_ToString(BinArr, Encoding := "UTF-8") {
oADO := ComObjCreate("ADODB.Stream")
oADO.Type := 1 ; adTypeBinary
oADO.Mode := 3 ; adModeReadWrite
oADO.Open
oADO.Write(BinArr)
oADO.Position := 0
oADO.Type := 2 ; adTypeText
oADO.Charset := Encoding
return oADO.ReadText, oADO.Close
}
BinArr_ToFile(BinArr, FileName) {
oADO := ComObjCreate("ADODB.Stream")
oADO.Type := 1 ; adTypeBinary
oADO.Open
oADO.Write(BinArr)
oADO.SaveToFile(FileName, 2)
oADO.Close
}
(With
CreateFormData() by
tmplinshi.)
Here,
photo_1 and
photo_2 are random names which you assign to specific files (please adjust filepaths). You can then
attach them via the
"attach://..." syntax.
I hope this helps. For your second question, I will return...