的Telegram Bot API支持多种输入形式:
我们支持GET
和POST
HTTP方法。我们支持博特API请求的参数传递四种方式:
- URL查询字符串
- 应用程序/ x-WWW窗体-urlencoded
- 应用/ JSON(除了上传文件)
- 多/表单数据(用于上传文件)
您正在使用最后一个选项。
Indy 9不支持Delphi 2009+或Unicode。的string
所有用途被假定为AnsiString
,这是在Delphi 7的情况下的任何AnsiString
添加到TIdMultipartFormDataStream
或TStrings
,即使是UTF-8编码的一个,将被发送原样通过TIdHTTP
。但是,没有选项可以指定服务器字符串数据实际使用UTF-8作为字符集。但是,根据文档:
所有查询必须使用UTF-8。
因此,不指定明确的字符集可能不是问题。
如果您仍然有问题multipart/form-data
,那么可以考虑使用application/x-www-form-urlencoded
(使用TIdHTTP.Post(TStrings)
)或application/json
(使用TIdHTTP.Post(TStream)
)代替:
procedure TBotThread.SendMessage(ChatID: String; Text: WideString; parse_mode: string; disable_notification: boolean);
var
Params: TStringList;
LHandler: TIdSSLIOHandlerSocket;
begin
if FShowBotLink then
Text := Text + LineBreak + FBotUser;
Params := TStringList.Create;
try
Params.Add('chat_id=' + UTF8Encode(ChatID));
if parse_mode <> '' then
Params.Add('parse_mode=' + UTF8Encode(parse_mode));
if disable_notification then
Params.Add('disable_notification=true')
else
Params.Add('disable_notification=false');
Params.Add('disable_web_page_preview=true');
Params.Add('text=' + UTF8Encode(Text));
LHandler := TIdSSLIOHandlerSocket.Create(nil);
try
LHandler.SSLOptions.Method := sslvTLSv1;
LHandler.SSLOptions.Mode := sslmClient;
FidHttpSend.HandleRedirects := true;
FidHttpSend.ReadTimeout := 30000;
FidHttpSend.IOHandler := LHandler;
try
try
FidHttpSend.Post(BaseUrl + API + '/sendmessage', Params, TStream(nil));
except
on E: EIdHTTPProtocolException do
begin
if E.ReplyErrorCode = 403 then
begin
WriteToLog('Bot was blocked by the user');
end;
end;
end;
finally
FidHttpSend.IOHandler := nil;
end;
finally
LHandler.Free;
end;
finally
Params.Free;
end;
end;
procedure TBotThread.SendMessage(ChatID: String; Text: WideString; parse_mode: string; disable_notification: boolean);
var
Params: TStringStream;
LHandler: TIdSSLIOHandlerSocket;
function JsonEncode(const wStr: WideString): string;
var
I: Integer;
Ch: WideChar;
begin
// JSON uses UTF-16 text, so no need to encode to UTF-8...
Result := '';
for I := 1 to Length(wStr) do
begin
Ch := wStr[i];
case Ch of
#8: Result := Result + '\b';
#9: Result := Result + '\t';
#10: Result := Result + '\n';
#12: Result := Result + '\f';
#13: Result := Result + '\r';
'"': Result := Result + '\"';
'\': Result := Result + '\\';
'/': Result := Result + '\/';
else
if (Ord(Ch) >= 32) and (Ord(Ch) <= 126) then
Result := Result + AnsiChar(Ord(wStr[i]))
else
Result := Result + '\u' + IntToHex(Ord(wStr[i]), 4);
end;
end;
end;
begin
if FShowBotLink then
Text := Text + LineBreak + FBotUser;
Params := TStringStream.Create('');
try
Params.WriteString('{');
Params.WriteString('chat_id: "' + JsonEncode(ChatID) + '",');
if parse_mode <> '' then
Params.WriteString('parse_mode: "' + JsonEncode(parse_mode) + '",')
if disable_notification then
Params.WriteString('disable_notification: True,')
else
Params.WriteString('disable_notification: False,');
Params.WriteString('disable_web_page_preview: True,');
Params.WriteString('text: "' + JsonEncode(Text) + '"');
Params.WriteString('}');
Params.Position := 0;
LHandler := TIdSSLIOHandlerSocket.Create(nil);
try
LHandler.SSLOptions.Method := sslvTLSv1;
LHandler.SSLOptions.Mode := sslmClient;
FidHttpSend.HandleRedirects := true;
FidHttpSend.ReadTimeout := 30000;
FidHttpSend.IOHandler := LHandler;
try
try
FidHttpSend.Request.ContentType := 'application/json';
FidHttpSend.Post(BaseUrl + API + '/sendmessage', Params, TStream(nil));
except
on E: EIdHTTPProtocolException do
begin
if E.ReplyErrorCode = 403 then
begin
WriteToLog('Bot was blocked by the user');
end;
end;
end;
finally
FidHttpSend.IOHandler := nil;
end;
finally
LHandler.Free;
end;
finally
Params.Free;
end;
end;
话虽这么说,你的函数的Text
参数是一个WideString
,它使用UTF-16,所以你应该能够发送任何Unicode文本,包括emojis。如果您尝试在代码中生成文本,请确保UTF-16正确编码任何非ASCII字符。例如,代码点U+1F601 GRINNING FACE WITH SMILING EYES
是宽字符$D83D $DE01
在UTF-16:
var
Text: WideString;
Text := 'hi ' + #$D83D#$DE01; // 'hi '
SendMessage('@channel', Text, 'Markup', False);
或者,你可以在你的短信使用HTML,所以你可以使用编码数字HTML实体非ASCII字符。根据文档:
支持所有数字HTML实体。
代码点U+1F601
是数字实体$#128513;
在HTML:
var
Text: WideString;
Text := 'hi $#128513;'; // 'hi '
SendMessage('@channel', Text, 'HTML', False);
印第安纳波利斯9不支持Unicode。你应该升级到Indy 10.如果这不是一个选项,我将不得不挖掘Indy 9的代码来为你提供其他选项。无论哪种方式,您实际发布的网址是?发布Unicode输入的要求是什么? –
感谢雷米的评论。我改变这一行发送电话表情符号。 Params.AddFormField('text',UTF8Encode(Text + LineBreak +#$ 0000260E));这适用于我,但这个代码不起作用:#$ 1F601为“磨脸微笑的眼睛”表情符号。我张贴到电报机器人API:https://api.telegram.org/bot。表情符号是unicode? 。对不起英语不好。 –
如何转换表情符号代码示例U + 1F601并在delphi中使用? –