Отправить эмодзи с помощью indy delphi7

Я хочу отправить эмодзи с помощью indy 9.00.10 на delphi 7. Я использую элементы управления tnt VCL. я нашел этот URL-адрес http://apps.timwhitlock.info/emoji/tables/unicode для юникода и байтового кода. как преобразовать эти коды в константы Delphi для отправки с помощью indy.

я использую этот код delphi для отправки сообщения боту телеграммы:

procedure TBotThread.SendMessage(ChatID:String; Text : WideString;
parse_mode:string;disable_notification:boolean);
Var
  Stream: TStringStream;
  Params: TIdMultipartFormDataStream;
  //Text : WideString;
  msg : WideString;
  Src : string;
  LHandler: TIdSSLIOHandlerSocket;
begin
  try
    try
      if FShowBotLink then
        Text := Text + LineBreak + FBotUser;
      msg := '/sendmessage';
      Stream := TStringStream.Create('');
      Params := TIdMultipartFormDataStream.Create;
      Params.AddFormField('chat_id',ChatID);
      if parse_mode <> '' then
        Params.AddFormField('parse_mode',parse_mode);
      if disable_notification then
        Params.AddFormField('disable_notification','true')
      else
        Params.AddFormField('disable_notification','false');
      Params.AddFormField('disable_web_page_preview','true');
      Params.AddFormField('text',UTF8Encode(Text));
      LHandler := TIdSSLIOHandlerSocket.Create(nil);
      FidHttpSend.ReadTimeout := 30000;
      FidHttpSend.IOHandler:=LHandler;
      LHandler.SSLOptions.Method := sslvTLSv1;
      LHandler.SSLOptions.Mode := sslmUnassigned;
      FidHttpSend.HandleRedirects := true;
      FidHttpSend.Post(BaseUrl + API + msg, Params, Stream);
    finally
      Params.Free;
      Stream.Free;
    ENd;
 except
   on E: EIdHTTPProtocolException do
   begin
      if E.ReplyErrorCode = 403 then
      begin
       WriteToLog('Bot was blocked by the user');
      end;
   end;
 end;  
end;

пример байтов для смайликов:

AERIAL_TRAMWAY = '\xf0\x9f\x9a\xa1';
AIRPLANE = '\xe2\x9c\x88';
ALARM_CLOCK = '\xe2\x8f\xb0';
ALIEN_MONSTER = '\xf0\x9f\x91\xbe';

Извините за плохой английский!!!


person Mehdi jafari    schedule 22.09.2016    source источник
comment
Indy 9 не поддерживает Юникод. Вы должны перейти на Indy 10. Если это не вариант, мне придется копаться в коде Indy 9, чтобы предоставить вам другие варианты. В любом случае, какой URL вы на самом деле отправляете? Каковы его требования для публикации ввода Unicode?   -  person Remy Lebeau    schedule 22.09.2016
comment
Спасибо Реми за ваш комментарий. я меняю эту строку, чтобы отправить смайлик на телефон. Params.AddFormField('text',UTF8Encode(Text + LineBreak + #$0000260E )); это работает для меня, но этот код не работает: # $ 1F601 для смайликов УСМЕИВАЮЩЕЕСЯ ЛИЦО С УЛЫБАЮЩИМСЯ ГЛАЗАМИ. я отправляю сообщение в API бота телеграммы: api.telegram.org/bot. смайлики в юникоде? . Извините за плохой английский.   -  person Mehdi jafari    schedule 22.09.2016
comment
как преобразовать пример кода emoji U + 1F601 и использовать в delphi?   -  person Mehdi jafari    schedule 22.09.2016


Ответы (1)


API Telegram Bot поддерживает несколько форм ввода:

Мы поддерживаем GET и POST методы HTTP. Мы поддерживаем четыре способа передачи параметров в запросах Bot API:

  • Строка запроса URL
  • приложение/x-www-форма-urlencoded
  • application/json (кроме загрузки файлов)
  • multipart/form-data (используйте для загрузки файлов)

Вы используете последний вариант.

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;

That being said, your function's Text parameter is a WideString, which uses UTF-16, so you should be able to send any Unicode text, including emojis. If you are trying to generate text in your code, just make sure you UTF-16 encode any non-ASCII characters correctly. For example, codepoint U+1F601 GRINNING FACE WITH SMILING EYES is wide chars $D83D $DE01 in UTF-16:

var
  Text: WideString;

Text := 'hi ' + #$D83D#$DE01; // 'hi ????'
SendMessage('@channel', Text, 'Markup', False);

Кроме того, вы можете использовать HTML в своих текстовых сообщениях, чтобы вы могли кодировать символы, отличные от ASCII, с помощью числовых объектов HTML. Согласно документам:

Поддерживаются все числовые сущности HTML.

Кодовая точка U+1F601 — это числовое значение $#128513; в HTML:

var
  Text: WideString;

Text := 'hi $#128513;'; // 'hi ????'
SendMessage('@channel', Text, 'HTML', False);
person Remy Lebeau    schedule 22.09.2016