Wolfram云中的TelegramBot

引言


这段时期过去了,关于哈布拉哈伯的每第二篇文章都致力于编写其电报机器人。 此外,一段时间后,可以轻松地将漫游器放置在您的计算机上或托管在俄罗斯。 六个月前,我的机器人刚刚在笔记本电脑上启动,并且在连接到API时没有遇到任何问题。 但是现在,当我想到让他重返工作岗位时,我意识到这并非易事。 我不想搜索和配置代理服务器,在国外甚至更多。 另外,在此之前,我用Wolfram语言编写了该机器人,却不知道该语言如何与代理服务器一起工作,因为我还没有使用过它们。 然后一个好主意出现了! 使用Wolfram Cloud。 在本文中,我想展示如何简单地进行注册,但是如果没有SMS,您可以启动用Wolfram语言编写的简单电报机器人。 在这些工具中,您仅需要浏览器。


关于Wolfram云的一点点


要访问云,您需要创建一个Wolfram帐户。 为此,请访问https://account.wolfram.com,并单击“创建一个”按钮后按照说明进行操作。



完成所有操作后,将在云的主页https://www.wolframcloud.com上显示所有产品及其使用计划。 您必须选择开发平台并创建一个新的笔记本。



稍后给出的所有代码将在此特定的云笔记本中执行。


关于电报机器人的一些知识


有许多专门针对他们的文章。 在这里,仅需说在执行所有其他操作之前,必须以标准方式创建机器人。 也就是说,只需与@BotFather机器人开始聊天并向他发送命令:


/newbot 

然后,您只需要按照说明输入名称并登录即可。 让他的名字叫Wolfram Cloud Bot并登录@ WolframCloud5973827Bot。



API实施


我们利用@BotFather的建议,并简要检查电报机器人的HTTP API。 实现整个API的任务还不值得。 要编写机器人,只需一小部分就足够了。 检查该API是否可访问,并且存在具有上述指定令牌的漫游器。 为此,只需执行一行:


 URLExecute["https://api.telegram.org/bot753681357:AAFqdRFN_QoODJxsBy3VN2sVwWTPKJEqteY/getMe"] 

出[..]:= ...
 {"ok" -> True, "result" -> {"id" -> 753681357, "is_bot" -> True, "first_name" -> "Wolfram Cloud Bot", "username" -> "WolframCloud5973827Bot"}} 

上面的命令是从Wolfram语言发出HTTP请求的最简单方法。 但是让我们复杂一点,以便于实现所有其他API方法。 让我们创建一个执行API请求的通用方法:


 TelegramBot::usage = "TelegramBot[token]"; $telegramAPI = "https://api.telegram.org"; telegramExecute[ TelegramBot[token_String], method_String, parameters: {(_String -> _)...}: {} ] := Module[{ request, requestURL, requestRules, requestBody, response, responseBody }, requestURL = URLBuild[{$telegramAPI, "bot" <> token, method}]; requestRules = DeleteCases[parameters, _[_String, Automatic | Null | None]]; requestBody = ImportString[ExportString[requestRules, "JSON"], "Text"]; request = HTTPRequest[requestURL, <| Method -> "POST", "ContentType" -> "application/json; charset=utf-8", "Body" -> requestBody |>]; response = URLRead[request]; responseBody = response["Body"]; Return[ImportString[responseBody, "RawJSON"]] ] 

检查这是否适用于上面已经测试过的方法:


 token = "753681357:AAFqdRFN_QoODJxsBy3VN2sVwWTPKJEqteY"; bot = TelegramBot[token]; telegramExecute[bot, "getMe"] 

出[..]:= ...
 <|"ok" -> True, "result" -> <|"id" -> 753681357, "is_bot" -> True, "first_name" -> "Wolfram Cloud Bot", "username" -> "WolframCloud5973827Bot"|>|> 

太好了 让我们创建一个单独的函数来执行机器人检查:



 getMe::usage="getMe[bot]"; TelegramBot /: getMe[bot_TelegramBot] := telegramExecute[bot, "getMe"] getMe[bot] 

出[..]:= ...
 <|"ok" -> True, "result" -> <|"id" -> 753681357, "is_bot" -> True, "first_name" -> "Wolfram Cloud Bot", "username" -> "WolframCloud5973827Bot"|>|> 

现在,以类似的方式可以添加在云中创建机器人所需的基本方法:



 getUpdates::usage = "getUpdates[bot, opts]"; Options[getUpdates] = { "offset" -> Automatic, "limit" -> Automatic, "timeout" -> Automatic, "allowed_updates" -> Automatic }; TelegramBot /: getUpdates[bot_TelegramBot, opts: OptionsPattern[getUpdates]] := telegramExecute[bot, "getUpdates", Flatten[{opts}]] 


 setWebhook::usage = "setWebhook[bot, url, opts]"; Options[setWebhook] = { "certificate" -> Automatic, "max_connections" -> Automatic, "allowed_updates" -> Automatic }; TelegramBot /: setWebhook[bot_TelegramBot, url_String, opts: OptionsPattern[setWebhook]] := telegramExecute[bot, "setWebhook", Join[{"url" -> url}, Flatten[{opts}]]] 


 deleteWebhook::usage = "deleteWebhook[bot]"; TelegramBot /: deleteWebhook[bot_TelegramBot] := telegramExecute[bot, "deleteWebhook"] 


 getWebhookInfo::usage = "getWebhookInfo[bot]"; TelegramBot /: getWebhookInfo[bot_TelegramBot] := telegramExecute[bot, "getWebhookInfo"] 


 sendMessage::usage = "sendMessage[bot, chat, text]"; Options[sendMessage] = { "parse_mode" -> Automatic, "disable_web_page_preview" -> Automatic, "disable_notification" -> Automatic, "reply_to_message_id" -> Automatic, "reply_markup" -> Automatic }; TelegramBot /: sendMessage[bot_TelegramBot, chat_Integer, text_String, opts: OptionsPattern[sendMessage]] := telegramExecute[ bot, "sendMessage", Join[{"chat_id" -> chat, "text" -> text}, Flatten[{opts}]] ] 

该API的最低版本已准备就绪。 让我们检查发送消息和接收更新的工作方式。 为此,请与我们的机器人进行聊天。 创建漫游器后,将发送带有/起始文本的第一条消息。 让我们看看它是否进入了更新列表:


 updates = getUpdates[bot] 

出[..]:= ...
 <|"ok" -> True, "result" -> {<|"update_id" -> 570790461, "message" -> <|"message_id" -> 1, "from" -> <|"id" -> 490138492, "is_bot" -> False, "first_name" -> "Kirill", "last_name" -> "Belov", "username" -> "KirillBelovTest"|>, "chat" -> <|"id" -> 490138492, "first_name" -> "Kirill", "last_name" -> "Belov", "username" -> "KirillBelovTest", "type" -> "private"|>, "date" -> 1542182547, "text" -> "/start", "entities" -> {<|"offset" -> 0, "length" -> 6, "type" -> "bot_command"|>}|>|>}|> 

您可以从更新列表中获取最新的更新数据,如下所示:


 lastUpdate = updates["result"][[-1]] 

出[..]:= ...
 <|"update_id" -> 570790461, "message" -> <|"message_id" -> 1, "from" -> <|"id" -> 490138492, "is_bot" -> False, "first_name" -> "Kirill", "last_name" -> "Belov", "username" -> "KirillBelovTest"|>, "chat" -> <|"id" -> 490138492, "first_name" -> "Kirill", "last_name" -> "Belov", "username" -> "KirillBelovTest", "type" -> "private"|>, "date" -> 1542182547, "text" -> "/start", "entities" -> {<|"offset" -> 0, "length" -> 6, "type" -> "bot_command"|>}|>|> 

这就是您如何获得消息的聊天记录以及消息文本本身的方法:


 chat = lastUpdate["message", "chat", "id"] text = lastUpdate["message", "text"] 

出[..]:= ...
 490138492 /start 

从结果中可以看到,一切就绪。 现在,我们将使用sendMessage代表机器人发送一条消息。


 sendMessage[bot, chat, "hello"] 

出[..]:= ...
 <|"ok" -> True, "result" -> <|"message_id" -> 2, "from" -> <|"id" -> 753681357, "is_bot" -> True, "first_name" -> "Wolfram Cloud Bot", "username" -> "WolframCloud5973827Bot"|>, "chat" -> <|"id" -> 490138492, "first_name" -> "Kirill", "last_name" -> "Belov", "username" -> "KirillBelovTest", "type" -> "private"|>, "date" -> 1542182601, "text" -> "hello"|>| > 


通常,这组功能已经足够。 但是,使用getUpdates方法不是很方便。 您需要提出一种使用webhook处理消息的方法。


创建webhook


Wolram Langauge具有使用API​​Function创建的一种特殊功能。 这是其中之一的示例:


 apiFunc = APIFunction[{"n" -> "Integer"}, Plot[Sin[#n * x], {x, -2Pi, 2Pi}]&, "PNG"]; apiFunc[{"n"->3}] 

出[..]:= ...


这些功能是专门为在云中部署而设计的。 此函数将接受一个请求参数作为输入。 要将其部署到云中,只需将功能本身转移到CloudDeploy。


 apiObject = CloudDeploy[apiFunc, "Deploy/apiObject"] 

出[..]:= ...
 CloudObject[https://www.wolframcloud.com/objects/kirillbelovtest/apiObject] 

然后,您可以在浏览器中单击链接并添加查询参数:



上面的函数处理了请求参数。 因此,您需要创建相同的函数来处理来自电报机器人的HTTP请求的主体(以Update对象的形式)。 为了生成地址,我们使用令牌来访问云对象更加困难。 还必须指出该对象具有公共访问权限,否则电报将无法访问网络挂钩。


 deployWebhook[bot_TelegramBot, handler_] := CloudDeploy[APIFunction[{}, handler[HTTPRequestData["Body"]] &], "Deploy/Webhooks/" <> Hash[bot, "SHA", "HexString"], Permissions -> "Public" ] 

handler是另一个函数处理程序。 让处理程序将请求主体的字符串转换为关联,从那里获取聊天标识符,然后将单词“ hello”发送回去。


 handlerHello[bot_TelegramBot][body_String] := Block[{json = ImportString[body, "RawJSON"], chat}, chat = json["message", "chat", "id"]; sendMessage[bot, chat, "hello"]; ] 

现在将时髦部署在云中。


 webhookObject = deployWebhook[bot, handlerHello[bot]] 

出[..]:= ...
 CloudObject[https://www.wolframcloud.com/objects/kirillbelovtest/Deploy/Webhooks/b9bd74f89348faecd6b683ba02637dd4d4028a28] 

最后一步是将该对象的地址传输到电报机器人。


 setWebhook[bot, webhookObject[[1]]] 

出[..]:= ...
 <|"ok" -> True, "result" -> True, "description" -> "Webhook was set"|> 

现在,我们将为该机器人编写一些内容,并查看其内容:



对话可以被认为是有效的。 为了更改现有处理程序的逻辑,只需重新部署云对象。 同时,您将不再需要为该机器人安装webhook。


答案逻辑


这将是在Wolfram云中创建机器人的过程的最后一部分。 此外,您可以用相同的方式使逻辑复杂化并添加新的API方法。 现在介绍对话本身。 假设在发送/ start命令后,该机器人返回了“ Hello”响应并更改了用户的键盘。 键盘上只剩下两个按钮:“你好”和“你是谁?” 我们以协会的形式实现对话。 密钥将是用户发送给机器人的命令。 关键值是漫游器响应本身和新键盘。 在这种情况下,许多按键和按钮应该完全匹配。 否则,当机器人不知道该怎么回答时,可能会出现这种情况。 当然,在这种情况下,您可以添加默认答案。


 keyboard[buttons : {__String}] := {"keyboard" -> {Table[{"text" -> button}, {button, buttons}]}, "resize_keyboard" -> True} $answers = <| (*user_text-><|"answer"->bot_text,"keyboard"->next_text|>*) "/start"-><|"answer"->"","keyboard"-> keyboard[{""," ?"}]|>, ""-><|"answer"->" ?", "keyboard" -> keyboard[{" ?"}]|> , " ?"-><|"answer"->"", "keyboard" -> keyboard[{""}]|> , " ?"-><|"answer"->"   Wolfram Language   ", "keyboard"->keyboard[{" ?"," ?"}]|> , " ?"-><|"answer"->"   :\nhttps://habr.com/post/422517/", "keyboard"->keyboard[{""," ?"}]|> , " ?"-><|"answer"->"  :\n@KirillBelovTest", "keyboard"->keyboard[{" ?",""}]|> , ""-><|"answer"->"", "keyboard"->keyboard[{""," ?"}]|> |>; answer[text_String] /; KeyExistsQ[$answers, text] := $answers[text] 

现在创建一个处理程序:


 handlerAbout[bot_TelegramBot][body_String] := Block[{json = ImportString[body, "RawJSON"], chat, text}, chat = json["message", "chat", "id"]; text = json["message", "text"]; sendMessage[bot, chat, answer[text]["answer"], "reply_markup" -> answer[text]["keyboard"]]; ] 

并重新部署云对象:


 deployWebhook[bot, handlerAbout[bot]]; 

我们来验证一下与机器人聊天时发生的情况。 但是首先,让我们清除消息历史记录:



功能扩展


到目前为止,与大量现有的机器人没有根本的区别。 也许喝酒也没有意义吗? 如果您了解这种机器人的优势,那么上面完成的所有工作的意义将是! 毕竟,他可以使用Wolfram语言和Wolrfam Cloud的所有功能。 机器人有必要求解方程吗? 这很容易! 您只需要重新定义答案即可!


 answer[text_String]["keyboard"] /; StringContainsQ[text, "  "] := Automatic answer[text_String]["answer"] /; StringContainsQ[text, "  "] := ToString[Flatten[Block[{args = StringSplit[text, "  "]}, Solve[ToExpression[args[[1]]], ToExpression[args[[2]]]] ]]] deployWebhook[bot, handlerAbout[bot]]; 


如果另外有人对云的功能感兴趣,那么可以在此处对其功能进行详细描述。


局限性


Wolfram Cloud是一个平台,可让您免费使用Wolfram语言,而Wolfram Research的主要产品Mathematica则要花钱。 因此,使用受到限制,我认为这些限制非常严格。 使用免费版本的开发平台时,每月为用户提供1000个云积分。 每笔云贷款都提供了时间来计算不同的类型。 由于本文讨论的是CloudDeploy + APIFunction,因此存储在云中的此类对象会在0.1秒的计算时间内花费1积分。 可以很容易地计算出,仅为用户免费提供了1分钟40秒的服务器时间来运行其应用程序(在本例中为bot)。 我在这里没有要补充的内容-它很小,非常小。 主要重点是使用浏览器在Development Platform中独立工作的用户。 实际上,在此模式下没有时间限制,而仅根据会话的持续时间和分配的资源。 通过这种使用,开发平台几乎可以构成完整的Mathematica,但不需要安装和许可。


Wolfram Cloud中的文章和代码

Source: https://habr.com/ru/post/zh-CN422517/


All Articles