原生推特(Twitter)客户端:第二部

21 九月 2020, 09:24
Soewono Effendi
1
2 589

概述

就像我在第一篇文章“无需 DLL 的 MT4/MT5 的原生推特(Twitter)客户端”中所承诺的那样;本文将尝试探索 Twitter API,从而能发送带有照片的推文。 为了令本文更容易理解,我仅关注上传图像。 到本文结尾,您应能得到一个可运行的推特客户端,且无需用到任何外部 DLL,这令您可发布最多四张照片的消息。 4 张照片的限制是由 Twitter API 设置,如参数 media_ids 中所述。


上传照片

有一种新方法,称为分块上传,在上传媒体时可用更好的方法来上传较大的文件,譬如视频或 GIF 动画。 出于我们的目的,我将关注简单方法,该方法仅限于仅上传图片。

请确保您已熟知推特的媒体类型和大小限制

将照片上传到推特只是一个简单的基本 OAuth 授权 HTTP multipart/form-data POST,我将在下个段落中对其进行解释。 已上传的每张照片都将返回一个 media_id,该 ID 仅在一定时间内有效,从而可在要发布的推文里包含它。

为了发布多达四张照片,所有返回的 media_id 都被简单地连接在一起,形成以逗号分隔的列表。

发布带照片推文的步骤如下:

  1. 上传照片并收集返回的 media_id
  2. 重复上传更多照片,直达上限。 4 张照片。 始终收集其返回的 media_id。
  3. 准备您的推文消息
  4. 发送推文时,请指定 media_id,并在列表里以逗号分隔所有要包含的 media_id。
注意:
为了令代码简单易懂,省略了错误处理。


HTTP multipart/form-data

为了将照片上传到推特,可将这些照片作为原始二进制数据或 Base64 编码的字符串上传。 建议将照片作为原始二进制数据上传,因为 Base64 编码的字符串的大小约暴涨三倍。

HTTP multipart/form-data 方法在 RFC-2388 中加以良好定义,但阅读本篇不错指南也许更容易理解。 基本上,从提到的文章中引用:“这是一个 HTTP POST 请求,其发送的请求主体已特别格式化为一个 "parts" 序列,并用 MIME 边界分隔。”

POST /submit.cgi HTTP/1.1
Host: example.com
User-Agent: curl/7.46.0
Accept: */*
Content-Length: 313
Expect: 100-continue
Content-Type: multipart/form-data; boundary=------------------------d74496d66958873e

--------------------------d74496d66958873e
Content-Disposition: form-data; name="person"

anonymous
--------------------------d74496d66958873e
Content-Disposition: form-data; name="secret"; filename="file.txt"
Content-Type: text/plain

contents of the file
--------------------------d74496d66958873e--


Twitter 类的实现如下:

   void              appendPhoto(string filename, string hash, uchar &data[],
                                 bool common_flag=false)
     {
      int flags=FILE_READ|FILE_BIN|FILE_SHARE_WRITE|FILE_SHARE_READ;
      if(common_flag)
         flags|=FILE_COMMON;
      //---
      int handle=FileOpen(filename,flags);
      if(handle==INVALID_HANDLE)
         return;
      //---
      int size=(int)FileSize(handle);
      uchar img[];
      ArrayResize(img,size);
      FileReadArray(handle,img,0,size);
      FileClose(handle);
      int pos = ArraySize(data);
      int offset = pos + size;
      int hlen = StringLen(hash)+6;
      int newlen = offset + hlen;
      ArrayResize(data, newlen);
      ArrayCopy(data, img, pos);
      StringToCharArray("\r\n--"+hash+"\r\n", data, offset, hlen);
     }

上面的代码将图像文件的原始二进制数据添加到 HTTP multipart/form-data post 的 “parts” 里。 POST 的 “envelope” 的代码完成如下,并指定了 Twitter Upload-API 参数 “media”。

   string              uploadPhoto(string filename)
     {
      // POST multipart/form-data
      string url = "https://upload.twitter.com/1.1/media/upload.json";
      //string url = "https://httpbin.org/anything";
      string params[][2];
      string query = oauthRequest(params, url, "POST");
      string o = getOauth(params);
      string custom_headers = "Content-Type: multipart/form-data;"
                              " boundary=";
      string boundary = getNonce();
      StringAdd(custom_headers, boundary); // use nonce as boundary string
      StringAdd(custom_headers, "\r\n");
      string headers = getHeaders(o, custom_headers, "upload.twitter.com");

      //string query = getQuery(params, url);
      //Print(query);
      uchar data[];
      string part = "\r\n--";
      StringAdd(part, boundary);
      StringAdd(part, "\r\nContent-Disposition: form-data;"
                " name=\"media\"\r\n\r\n");
      StringToCharArray(part, data, 0, StringLen(part));
      appendPhoto(filename, boundary, data);
      string resp = SendRequest("POST", url, data, headers);;
      if(m_verbose)
        {
         SaveToFile(filename + "_post.txt", data);
         Print(resp);
        }
      return (getTokenValue(resp, "media_id"));
     }

为了检查和验证构建的 HTTP multipart/form-data,把 HTTP 请求另外保存在 MT 终端的数据文件夹中,以便进行进一步检查。


带照片的推文

出于简洁起见,我用了一个简单的函数 getTokenValue() 来提取 Twitter Upload-API 返回的 media_id。 您可能会考虑使用出色的 MQL5.com 上提供的 JSON 库。 

以下代码展示了一种非常简单使用 Twitter 类的方法。 函数 Screenshots() 简单地捕获当前打开图表的屏幕截图,并构建一条简单的推文消息。 最多能选择四个图表。
每个屏幕截图均保存到文件,其文件名在字符串数组 fnames 里返回。

屏幕截图被逐一上传,收集返回的 media_id,合并的列表则以逗号分隔。
依据上述逗号分隔列表中指定的 media_ids 参数,我们发布带有这些屏幕截图的推文消息,并将这些屏幕截图附加到推文里。

就是如此容易。

   CTwitter tw(consumer_key, consumer_secret,
               access_token, access_secret, verbose);

   // Gather information
   string fnames[4];
   string msg;
   Screenshots(fnames, msg);

   // Upload screenshots
   int n = ArraySize(fnames);
   int i = n - 1;
   // create comma separated media_ids
   string medias = tw.uploadPhoto(fnames[i]);
   for(i= n - 2; i>=0; i--)
   {
      StringAdd(medias, ",");
      StringAdd(medias, tw.uploadPhoto(fnames[i]));
   }
   
   // Send Tweet with photos' ids
   string resp = tw.tweet(msg, medias);
   Print(resp);


Twitter 类

您可以在 Twitter.mqh 中找到 Twitter 类,其目标是独立于其他包含文件。 若要发送带有照片的推文,这一个文件就能满足您全部需求了。

首先,实例化一个 Twitter 对象,指定您的使用者和访问令牌,并带有一个可选的冗长标志,这有助于在开发过程中进行调试。

   CTwitter tw(consumer_key, consumer_secret,
               access_token, access_secret, verbose);

然后,您可以尝试调用可用的公开函数:

  • verifyCredentials() 
    返回您的访问令牌 Twitter ID
  • uploadPhoto()
    上传照片,并返回其 media_id
  • tweet()
    发送带有可选 media_ids 的推文

还有一些辅助函数:

  • getTokenValue()
    从 json 字符串返回令牌/参数的值。
    注意: 这是一个非常简单的字符串解析,不要期望能与 json 完全兼容。
  • unquote()
    从字符串中删除引号。


在推特上发布您的图表

附件是一个有效的 MT5 脚本,该脚本可捕获多达四个图表的屏幕截图,并构建一条简单的推文消息,其中包含图表的品种和 OHLCV 值。
这是一个简单的示例,是您开始自行研发智能系统和/或脚本的起点。
注意:

您必须指定自己的使用者、访问令牌和密匙。

以下是脚本发送的推文示例。

自 MT5 发送的带照片推文

图例 1. 自 MT5 发送的带照片推文


推特上的完整 MT5 图表

图例 2. 推特上的全尺寸 MT5 图表 


当然,您也可以附加任何照片;)

幸运猫推文

图例 3. 幸运猫推文


结束语

此处为您提供了一个简单易用的 Twitter 类作为自包含文件,令您轻松发布图表和信号。 还示意了相关的技术细节,希望它们可以很容易就理解。

这个 Twitter 类还远未完工,还有许多其他 Twitter API 会添加到该类之中。 请随时在评论中发表您的改进意见,这都会令 MQL5 社区受益。

我希望您阅读本文时能感到愉悦,就像我写这篇文章时一样。
我也希望您可以用所提供的代码来得到乐趣和收益。

尽享快乐。


由MetaQuotes Software Corp.从英文翻译成
原始文章: https://www.mql5.com/en/articles/8318

附加的文件 |
Twitter.mqh (19.77 KB)
TwitterDemo.mq5 (4.87 KB)
最近评论 | 前往讨论 (1)
程序化智能交易
程序化智能交易 | 27 9月 2020 在 17:58

你好,大神!

可以讲一下如何获取电脑MAC地址的方法吗,这样可以实现EA指标的电脑加密功能!

谢谢了。

无需 DLL 的原生 MT4/MT5 推特(Twitter)客户端 无需 DLL 的原生 MT4/MT5 推特(Twitter)客户端

是否曾想访问推文和/或在推特(Twitter)上发布您的交易信号? 无需更多搜索,这些持续更新的系列文章将为您展示如何无需任何 DLL 的情况下进行操作。 畅想 MQL 实现 Twitter API 的旅程。 在第一部分中,我们将在访问 Twitter API 时遵循身份验证和授权的荣耀之路。

MQL 作为 MQL 程序图形界面的标记工具(第三部)。 窗体设计师 MQL 作为 MQL 程序图形界面的标记工具(第三部)。 窗体设计师

在篇论文当中,我们将用 MQL 的结构完成构建 MQL 程序窗口界面的概念讲述。 专业的图形编辑器能够交互式地设置由 GUI 元素的基本类组成的布局,然后将其以 MQL 描述导出,从而可在您的 MQL 项目中使用。 此片论文介绍了编辑器的内部设计和用户指南。 附带源代码。

DoEasy 函数库中的时间序列(第四十四部分):指标缓冲区对象类集合 DoEasy 函数库中的时间序列(第四十四部分):指标缓冲区对象类集合

本文介绍如何创建指标缓冲区对象类的集合。 我计划测试为指标创建和操控任意数量缓冲区的能力(在 MQL 指标中可以创建的最大缓冲区数量为 512)。

手工图表和交易工具包(第一部分)。 准备:结构描述和助手类 手工图表和交易工具包(第一部分)。 准备:结构描述和助手类

这是该系列的第一篇文章,我将在其中讲述一个工具箱,该工具箱可通过键盘快捷键来手工图表图形应用。 这非常方便:按一个键,然后出现趋势线,再按另一个键 — 将创建具有必要参数的斐波那契扇形。 也可以切换时间帧,重新排列图层或从图表中删除所有对象。