Notebook[{ Cell[CellGroupData[{ Cell["Simple Telegram bot demo", "Section"], Cell[TextData[{ "If you are new to Telegram bots first check the ", ButtonBox["introduction to bots", BaseStyle->"Hyperlink", ButtonData->{ URL["https://core.telegram.org/bots"], None}, ButtonNote->"https://core.telegram.org/bots"], " and the ", ButtonBox["introduction to the bot API", BaseStyle->"Hyperlink", ButtonData->{ URL["https://core.telegram.org/bots/api"], None}, ButtonNote->"https://core.telegram.org/bots/api"], "." }], "Text"], Cell["\<\ If you haven\[CloseCurlyQuote]t installed the package you may call either \ automated install with:\ \>", "Text"], Cell[BoxData[ RowBox[{"Get", "[", "\"\\"", "]"}]], "Input"], Cell["Or online version with:", "Text"], Cell[BoxData[ RowBox[{"Get", "[", "\"\\"", "]"}]], "Input"], Cell[BoxData[ RowBox[{"Needs", "[", "\"\\"", "]"}]], "Input", InitializationCell->True], Cell["Path to a configuration file in JSON format", "Text"], Cell[BoxData[ RowBox[{ RowBox[{"$BotConfigFile", " ", "=", " ", RowBox[{"FileNameJoin", "[", RowBox[{"{", RowBox[{ RowBox[{"NotebookDirectory", "[", "]"}], ",", "\"\\""}], "}"}], "]"}]}], ";"}]], "Input", InitializationCell->True], Cell[TextData[{ "Path to a temp directory used by the bot. Note this directory ", StyleBox["must exist", FontWeight->"Bold"], "." }], "Text"], Cell[BoxData[{ RowBox[{ RowBox[{"$BotTmpDir", " ", "=", " ", RowBox[{"FileNameJoin", "[", RowBox[{"{", RowBox[{ RowBox[{"NotebookDirectory", "[", "]"}], ",", "\"\\""}], "}"}], "]"}]}], ";"}], "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{"If", "[", RowBox[{ RowBox[{"Not", "[", RowBox[{"FileExistsQ", "[", "$BotTmpDir", "]"}], "]"}], ",", RowBox[{"CreateDirectory", "[", "$BotTmpDir", "]"}]}], "]"}], ";"}], " ", RowBox[{"(*", RowBox[{ "Try", " ", "to", " ", "create", " ", "the", " ", "folder", " ", "if", " ", "it", " ", "does", " ", "not", " ", "exist"}], "*)"}]}]}], "Input", InitializationCell->True], Cell[TextData[{ "The ", StyleBox["config file", FontWeight->"Bold"], " is a JSON where some parameters are defined. As a first example you may \ paste the following in the path selected by $BotConfigFile:\n\n{\n \ \[OpenCurlyDoubleQuote]FriendList\[CloseCurlyDoubleQuote]: [ ],\n \ \[OpenCurlyDoubleQuote]Token\[CloseCurlyDoubleQuote]: \ \[OpenCurlyDoubleQuote]PasteYourTokenHere\[CloseCurlyDoubleQuote],\n \ \[OpenCurlyDoubleQuote]MasterList\[CloseCurlyDoubleQuote]: [ ],\n \ \[OpenCurlyDoubleQuote]LastAnswered\[CloseCurlyDoubleQuote]: 1,\n \ \[OpenCurlyDoubleQuote]ErrorNoCmd\[CloseCurlyDoubleQuote]: \ \[OpenCurlyDoubleQuote]Please, send me a command.\[CloseCurlyDoubleQuote],\n \ \[OpenCurlyDoubleQuote]ErrorUnknownCmd\[CloseCurlyDoubleQuote]: \ \[OpenCurlyDoubleQuote]I do not know such a command.\[CloseCurlyDoubleQuote],\ \n \[OpenCurlyDoubleQuote]ErrorUnprivilegedCmd\[CloseCurlyDoubleQuote]: \ \[OpenCurlyDoubleQuote]You are not allowed to do \ that.\[CloseCurlyDoubleQuote]\n}\n" }], "Text"], Cell[TextData[{ StyleBox["Fields in the config file", FontWeight->"Bold"], ":\n", StyleBox["Token", FontSlant->"Italic"], " is the value authenticating your bot (see ", ButtonBox["here", BaseStyle->"Hyperlink", ButtonData->{ URL["https://core.telegram.org/bots/api#authorizing-your-bot"], None}, ButtonNote->"https://core.telegram.org/bots/api#authorizing-your-bot"], "). Get it and put it there.\n", StyleBox["MasterList", FontSlant->"Italic"], " is a list of integers identifying the users allowed to call any command \ (privilege 2). Might be empty []. Later you\[CloseCurlyQuote]d probably like \ to enter your user id in the MasterList. You can check it when the bot \ receives your messages.\n", StyleBox["FriendList", FontSlant->"Italic"], " is a list of integers identifying the users allowed to call some commands \ (privilege 1). Might be empty [].\nAny user out of these lists will be \ assigned privilege 0.\nIf no risky command is allowed you may leave those \ empty and allow every user to execute any command.\n", StyleBox["LastAnswered", FontSlant->"Italic"], " is the integer identifying the last message answered. Messages are stored \ in the servers up to 24 hours, this is used to avoid answering multiple times \ when restarting the bot.\nBEWARE: as such integer will eventually overflow \ the bot will stop answering when that happens. Manually change the parameter \ in the config file to 1 when that happens.\n\nApart from that, you can store \ any option in the config file. The sample file shows 3 strings, which are \ read by some default functions in the package." }], "Text"], Cell[TextData[{ "The ", StyleBox["bot\[CloseCurlyQuote]s command list", FontWeight->"Bold"], " consists on:\n1- A string identifying the command in Telegram. Messages \ starting with \\thisString will be understood as calling this command. It \ should correspond to the ones registered in the bot (see ", ButtonBox["here", BaseStyle->"Hyperlink", ButtonData->{ URL["https://core.telegram.org/bots#edit-settings"], None}, ButtonNote->"https://core.telegram.org/bots#edit-settings"], "), but it is not mandatory.\n2 - An element of {0, 1, 2} referring to the \ minimum privilege needed to execute the command. 0 = anyone, 1 = friends, 2 = \ masters.\n3 - The ", StyleBox["Mathematica", FontSlant->"Italic"], " function associated with the command.\n These functions receive two \ JSON arguments: the message that initiated the call and the bot itself.\n \ They MUST return a list of elements:\n \ti) A boolean value indicating if \ the message was considered complete or not. If # === False, the bot \ understands the command is not completed yet. The next message will be \ preprocessed to have the command added. This is useful for mobile interfaces, \ where the command is selected from a list. It can also be used to set up a \ ReplyKeyboard. Any other value from False is understood as completed.\n \t\ ii) An object representing the result of the API called to answer the \ message. Package provided functions like BotAnswerMsg return appropriate JSON \ objects or $Failed if failed. This object is used to decide whether to retry \ API calling if failed (e.g., due to internet connection lost) and to update \ LastAnswered if succeeded." }], "Text"], Cell[BoxData[ RowBox[{ RowBox[{"$BotCmdList", " ", "=", " ", RowBox[{"{", RowBox[{ RowBox[{"{", RowBox[{"\"\\"", ",", " ", "0", ",", " ", "CmdWhoami"}], "}"}], ",", " ", RowBox[{"{", RowBox[{"\"\\"", ",", " ", "2", ",", " ", "CmdWolfram"}], "}"}], ",", " ", RowBox[{"{", RowBox[{"\"\\"", ",", "\n", " ", "2", ",", " ", "CmdShell"}], "}"}], ",", " ", RowBox[{"{", RowBox[{"\"\\"", ",", " ", "0", ",", " ", "CmdPing"}], "}"}], ",", RowBox[{"{", RowBox[{"\"\\"", ",", " ", "1", ",", " ", "CmdMusic"}], "}"}], ",", RowBox[{"{", RowBox[{"\"\\"", ",", " ", "0", ",", " ", "CmdCustomKb"}], "}"}], ",", RowBox[{"{", RowBox[{"\"\\"", ",", " ", "1", ",", " ", "CmdWeather"}], "}"}]}], "}"}]}], ";"}]], "Input", InitializationCell->True], Cell["\<\ Implementation of demo commands. Check the package provided functions with ?, e.g.:\ \>", "Text"], Cell[BoxData[ RowBox[{"?", "BotAnswerMsg"}]], "Input"], Cell["Return a sentence based on your privilege level", "Text"], Cell[BoxData[ RowBox[{ RowBox[{"CmdWhoami", "[", RowBox[{"msg_", ",", "bot_"}], "]"}], " ", ":=", " ", "\n", " ", RowBox[{"Block", "[", RowBox[{ RowBox[{"{", RowBox[{"fromid", ",", " ", "str", ",", " ", "msgId"}], "}"}], ",", "\[IndentingNewLine]", RowBox[{ RowBox[{"fromid", " ", "=", " ", RowBox[{"JSONElement", "[", RowBox[{"msg", ",", RowBox[{"{", RowBox[{"\"\\"", ",", "\"\\"", ",", "\"\\""}], "}"}]}], "]"}]}], ";", "\n", " ", RowBox[{"msgId", " ", "=", " ", RowBox[{"JSONElement", "[", RowBox[{"msg", ",", RowBox[{"{", RowBox[{"\"\\"", ",", "\"\\""}], "}"}]}], "]"}]}], ";", "\n", " ", RowBox[{"str", " ", "=", " ", RowBox[{"Switch", "[", RowBox[{ RowBox[{"BotUserPrivilege", "[", RowBox[{"fromid", ",", "bot"}], "]"}], ",", " ", "2", ",", " ", "\n", " ", "\"\\"", ",", " ", "1", ",", " ", "\n", " ", "\"\\"", ",", " ", "_", ",", " ", "\n", " ", "\"\\""}], "]"}]}], ";", "\n", " ", RowBox[{"{", RowBox[{"True", ",", RowBox[{"BotAnswerMsg", "[", RowBox[{"msg", ",", " ", "str", ",", "bot"}], "]"}]}], "}"}]}]}], "\n", " ", "]"}]}]], "Input", InitializationCell->True], Cell["\<\ Execute a Wolfram statement (very dangerous, do not allow to strangers!)\ \>", "Text"], Cell[BoxData[ RowBox[{ RowBox[{"CmdWolfram", "[", RowBox[{"msg_", ",", "bot_"}], "]"}], " ", ":=", " ", "\n", " ", RowBox[{"Block", "[", RowBox[{ RowBox[{"{", RowBox[{ "fromid", ",", " ", "strSplit", ",", "msgId", ",", "eval", ",", "filePath"}], "}"}], ",", " ", RowBox[{ RowBox[{"fromid", " ", "=", " ", RowBox[{"JSONElement", "[", RowBox[{"msg", ",", RowBox[{"{", RowBox[{"\"\\"", ",", "\"\\"", ",", "\"\\""}], "}"}]}], "]"}]}], ";", "\n", " ", RowBox[{"msgId", " ", "=", " ", RowBox[{"JSONElement", "[", RowBox[{"msg", ",", RowBox[{"{", RowBox[{"\"\\"", ",", "\"\\""}], "}"}]}], "]"}]}], ";", "\[IndentingNewLine]", RowBox[{"strSplit", "=", RowBox[{"StringSplit", "[", RowBox[{ RowBox[{"JSONElement", "[", RowBox[{"msg", ",", RowBox[{"{", RowBox[{"\"\\"", ",", "\"\\""}], "}"}]}], "]"}], ",", " ", "Whitespace", ",", " ", "2"}], "]"}]}], ";", "\[IndentingNewLine]", RowBox[{"If", "[", RowBox[{ RowBox[{ RowBox[{ RowBox[{"Length", "[", "strSplit", "]"}], "<=", "1"}], "||", RowBox[{ RowBox[{"strSplit", "[", RowBox[{"[", "2", "]"}], "]"}], "\[Equal]", "\"\<\>\""}]}], ",", "\[IndentingNewLine]", RowBox[{"(*", RowBox[{"No", " ", "additional", " ", "arguments", " ", "were", " ", RowBox[{"given", ".", " ", "Wait"}], " ", "thus", " ", "for", " ", RowBox[{"them", "."}]}], "*)"}], "\[IndentingNewLine]", RowBox[{"{", RowBox[{"False", ",", "Null"}], "}"}], ",", "\[IndentingNewLine]", RowBox[{"(*", RowBox[{"Otherwise", " ", "evaluate", " ", "them"}], "*)"}], "\[IndentingNewLine]", RowBox[{ RowBox[{"eval", "=", RowBox[{"ToExpression", "[", RowBox[{"strSplit", "[", RowBox[{"[", "2", "]"}], "]"}], "]"}]}], ";", "\[IndentingNewLine]", RowBox[{"(*", RowBox[{ RowBox[{ "If", " ", "the", " ", "result", " ", "is", " ", "a", " ", "Graphics", " ", "object"}], ",", " ", RowBox[{"export", " ", "it", " ", "and", " ", "sent", " ", RowBox[{"it", "."}]}]}], "*)"}], "\[IndentingNewLine]", RowBox[{"Switch", "[", RowBox[{ RowBox[{"Head", "[", "eval", "]"}], ",", "Graphics", ",", RowBox[{ RowBox[{"filePath", "=", RowBox[{"FileNameJoin", "[", RowBox[{"{", RowBox[{"$BotTmpDir", ",", RowBox[{ RowBox[{"DateString", "[", RowBox[{"{", RowBox[{ "\"\\"", ",", "\"\\"", ",", "\"\\"", ",", "\"\\"", ",", "\"\\"", ",", "\"\\""}], "}"}], "]"}], "<>", "\"\<.png\>\""}]}], "}"}], "]"}]}], ";", "\[IndentingNewLine]", "\t\t\t\t\t\t\t", RowBox[{"Export", "[", RowBox[{"filePath", ",", "eval"}], "]"}], ";", "\[IndentingNewLine]", "\t\t\t\t\t\t\t", RowBox[{"{", RowBox[{"True", ",", RowBox[{"BotPhotoAnswerMsg", "[", RowBox[{"msg", ",", "filePath", ",", "bot"}], "]"}]}], "}"}]}], ",", "\[IndentingNewLine]", RowBox[{"(*", RowBox[{"Otherwise", ",", " ", RowBox[{"send", " ", "the", " ", "String"}]}], "*)"}], "\[IndentingNewLine]", "_", ",", RowBox[{"{", RowBox[{"True", ",", RowBox[{"BotAnswerMsg", "[", RowBox[{"msg", ",", RowBox[{"ToString", "[", "eval", "]"}], ",", "bot"}], "]"}]}], "}"}]}], "\[IndentingNewLine]", "]"}]}]}], "\n", " ", "]"}]}]}], "\n", " ", "]"}]}]], "Input", InitializationCell->True], Cell["\<\ Execute a shell statement (very dangerous, do not allow to strangers!)\ \>", "Text"], Cell[BoxData[ RowBox[{ RowBox[{"CmdShell", "[", RowBox[{"msg_", ",", "bot_"}], "]"}], " ", ":=", " ", "\n", " ", RowBox[{"Block", "[", RowBox[{ RowBox[{"{", RowBox[{"fromid", ",", " ", "msgId", ",", " ", "ret", ",", "strSplit"}], "}"}], ",", " ", "\n", " ", RowBox[{ RowBox[{"fromid", " ", "=", " ", RowBox[{"JSONElement", "[", RowBox[{"msg", ",", RowBox[{"{", RowBox[{"\"\\"", ",", "\"\\"", ",", "\"\\""}], "}"}]}], "]"}]}], ";", "\n", " ", RowBox[{"msgId", " ", "=", " ", RowBox[{"JSONElement", "[", RowBox[{"msg", ",", RowBox[{"{", RowBox[{"\"\\"", ",", "\"\\""}], "}"}]}], "]"}]}], ";", "\[IndentingNewLine]", RowBox[{"strSplit", "=", RowBox[{"StringSplit", "[", RowBox[{ RowBox[{"JSONElement", "[", RowBox[{"msg", ",", RowBox[{"{", RowBox[{"\"\\"", ",", "\"\\""}], "}"}]}], "]"}], ",", " ", "Whitespace", ",", " ", "2"}], "]"}]}], ";", "\[IndentingNewLine]", RowBox[{"If", "[", RowBox[{ RowBox[{ RowBox[{ RowBox[{"Length", "[", "strSplit", "]"}], "<=", "1"}], "||", RowBox[{ RowBox[{"strSplit", "[", RowBox[{"[", "2", "]"}], "]"}], "\[Equal]", "\"\<\>\""}]}], ",", "\[IndentingNewLine]", RowBox[{"(*", RowBox[{"No", " ", "additional", " ", "arguments", " ", "were", " ", RowBox[{"given", ".", " ", "Wait"}], " ", "thus", " ", "for", " ", RowBox[{"them", "."}]}], "*)"}], "\[IndentingNewLine]", RowBox[{"{", RowBox[{"False", ",", "Null"}], "}"}], ",", "\[IndentingNewLine]", RowBox[{"(*", RowBox[{"Otherwise", " ", "evaluate", " ", "them"}], "*)"}], "\[IndentingNewLine]", RowBox[{ RowBox[{"ret", " ", "=", " ", RowBox[{"RunProcess", "[", RowBox[{ "$SystemShell", ",", " ", "\"\\"", ",", " ", RowBox[{ RowBox[{"strSplit", "[", RowBox[{"[", "2", "]"}], "]"}], " ", "<>", " ", "\"\<\\nexit\\n\>\""}]}], "]"}]}], ";", "\[IndentingNewLine]", RowBox[{"(*", RowBox[{ RowBox[{ "Here", " ", "is", " ", "a", " ", "example", " ", "of", " ", "using", " ", "BotAPICall", " ", "to", " ", "do", " ", "the", " ", "same", " ", "as", " ", "BotAnswerMsg"}], ",", " ", RowBox[{ "manually", " ", "controlling", " ", "the", " ", "parameters"}]}], "*)"}], "\n", " ", RowBox[{"{", RowBox[{"True", ",", RowBox[{"BotAPICall", "[", "\n", " ", RowBox[{"\"\\"", ",", " ", RowBox[{"{", RowBox[{ RowBox[{"\"\\"", " ", "->", " ", "fromid"}], ",", " ", RowBox[{"\"\\"", " ", "->", " ", "ret"}], ",", " ", "\n", " ", RowBox[{ "\"\\"", " ", "->", " ", "msgId"}]}], "}"}], ",", "bot"}], "]"}]}], "}"}]}]}], "\[IndentingNewLine]", "]"}]}]}], "\n", " ", "]"}]}]], "Input", InitializationCell->True], Cell["\<\ Measure time between received message time and bot\[CloseCurlyQuote]s local \ time when answering\ \>", "Text"], Cell[BoxData[ RowBox[{ RowBox[{"CmdPing", "[", RowBox[{"msg_", ",", "bot_"}], "]"}], " ", ":=", " ", "\n", " ", RowBox[{"Block", "[", RowBox[{ RowBox[{"{", "time", "}"}], ",", " ", RowBox[{ RowBox[{"time", " ", "=", " ", RowBox[{"JSONElement", "[", RowBox[{"msg", ",", RowBox[{"{", RowBox[{"\"\\"", ",", "\"\\""}], "}"}]}], "]"}]}], ";", "\n", " ", RowBox[{"{", RowBox[{"True", ",", " ", RowBox[{"BotAnswerMsg", "[", RowBox[{"msg", ",", " ", RowBox[{"\"\\"", " ", "<>", " ", RowBox[{"ToString", "[", RowBox[{ RowBox[{"UnixTime", "[", "]"}], " ", "-", " ", "time"}], "]"}], " ", "<>", " ", "\"\< s.\>\""}], ",", "bot"}], "]"}]}], "}"}]}]}], "\n", " ", "]"}]}]], "Input", InitializationCell->True], Cell["Sending a random music file", "Text"], Cell[BoxData[ RowBox[{ RowBox[{"CmdMusic", "[", RowBox[{"msg_", ",", "bot_"}], "]"}], " ", ":=", " ", "\n", " ", RowBox[{"Block", "[", RowBox[{ RowBox[{"{", "filePath", "}"}], ",", " ", RowBox[{ RowBox[{"filePath", "=", RowBox[{"FileNameJoin", "[", RowBox[{"{", RowBox[{"$BotTmpDir", ",", RowBox[{ RowBox[{"DateString", "[", RowBox[{"{", RowBox[{ "\"\\"", ",", "\"\\"", ",", "\"\\"", ",", "\"\\"", ",", "\"\\"", ",", "\"\\""}], "}"}], "]"}], "<>", "\"\<.mp3\>\""}]}], "}"}], "]"}]}], ";", "\[IndentingNewLine]", RowBox[{"(*", RowBox[{ "Generate", " ", "random", " ", "music", " ", "using", " ", "notes", " ", "in", " ", "the", " ", "Aristoxenian", " ", "scale"}], "*)"}], "\[IndentingNewLine]", RowBox[{ RowBox[{"Export", "[", RowBox[{"filePath", ",", RowBox[{"Sound", "[", RowBox[{ RowBox[{ RowBox[{"Play", "[", RowBox[{ RowBox[{"Sin", "[", RowBox[{"#", " ", "2", "Pi", " ", "t"}], "]"}], ",", RowBox[{"{", RowBox[{"t", ",", "0", ",", "0.5"}], "}"}], ",", RowBox[{"SampleRate", "\[Rule]", "2000"}]}], "]"}], "&"}], "/@", RowBox[{"RandomChoice", "[", RowBox[{ RowBox[{"(", RowBox[{ RowBox[{"{", RowBox[{"1", ",", RowBox[{"9", "/", "8"}], ",", RowBox[{"5", "/", "4"}], ",", RowBox[{"4", "/", "3"}], ",", RowBox[{"3", "/", "2"}], ",", RowBox[{"5", "/", "3"}], ",", RowBox[{"15", "/", "8"}], ",", RowBox[{"2", "/", "1"}]}], "}"}], "*", "440", "*", RowBox[{"3", "/", "5"}]}], ")"}], ",", "20"}], "]"}]}], "]"}]}], "]"}], "\n", " ", RowBox[{"{", RowBox[{"True", ",", " ", RowBox[{"BotAudioAnswerMsg", "[", RowBox[{"msg", ",", " ", "filePath", ",", "bot"}], "]"}]}], "}"}]}]}]}], "\n", " ", "]"}]}]], "Input", InitializationCell->True], Cell["Setting an example custom keyboard", "Text"], Cell[BoxData[ RowBox[{ RowBox[{"CmdCustomKb", "[", RowBox[{"msg_", ",", "bot_"}], "]"}], " ", ":=", " ", "\n", " ", RowBox[{"Block", "[", RowBox[{ RowBox[{"{", RowBox[{ "fromid", ",", " ", "strSplit", ",", "msgId", ",", "eval", ",", "filePath"}], "}"}], ",", " ", RowBox[{ RowBox[{"fromid", " ", "=", " ", RowBox[{"JSONElement", "[", RowBox[{"msg", ",", RowBox[{"{", RowBox[{"\"\\"", ",", "\"\\"", ",", "\"\\""}], "}"}]}], "]"}]}], ";", "\n", " ", RowBox[{"msgId", " ", "=", " ", RowBox[{"JSONElement", "[", RowBox[{"msg", ",", RowBox[{"{", RowBox[{"\"\\"", ",", "\"\\""}], "}"}]}], "]"}]}], ";", "\[IndentingNewLine]", RowBox[{"strSplit", "=", RowBox[{"StringSplit", "[", RowBox[{ RowBox[{"JSONElement", "[", RowBox[{"msg", ",", RowBox[{"{", RowBox[{"\"\\"", ",", "\"\\""}], "}"}]}], "]"}], ",", " ", "Whitespace", ",", " ", "2"}], "]"}]}], ";", "\[IndentingNewLine]", RowBox[{"{", RowBox[{"True", ",", RowBox[{"BotAPICall", "[", " ", RowBox[{"\"\\"", ",", " ", RowBox[{"{", RowBox[{ RowBox[{"\"\\"", " ", "->", " ", "fromid"}], ",", " ", RowBox[{ "\"\\"", " ", "->", " ", "\"\\""}], ",", " ", RowBox[{"\"\\"", " ", "->", " ", "msgId"}], ",", RowBox[{"\"\\"", "\[Rule]", RowBox[{"BotPrepareKeyboard", "[", RowBox[{"{", RowBox[{ RowBox[{"{", RowBox[{ "\"\\"", ",", "\"\\"", ",", "\"\\""}], "}"}], ",", RowBox[{"{", RowBox[{ "\"\\"", ",", "\"\\"", ",", "\"\\""}], "}"}], ",", RowBox[{"{", "\"\\"", "}"}], ",", RowBox[{"{", "\"\\"", "}"}]}], "}"}], "]"}]}]}], "}"}], ",", "bot"}], "]"}]}], "}"}]}]}], "\n", " ", "]"}]}]], "Input", InitializationCell->True], Cell["\<\ Use a previously given location to find weather data. When a user sends its \ location, it is saved as a rule in BotUserLocation, which is read by the \ command.\ \>", "Text"], Cell[BoxData[ RowBox[{ RowBox[{"CmdWeather", "[", RowBox[{"msg_", ",", "bot_"}], "]"}], " ", ":=", " ", "\n", " ", RowBox[{"Block", "[", RowBox[{ RowBox[{"{", RowBox[{"fromid", ",", "loc"}], "}"}], ",", "\[IndentingNewLine]", RowBox[{ RowBox[{"fromid", " ", "=", " ", RowBox[{"JSONElement", "[", RowBox[{"msg", ",", RowBox[{"{", RowBox[{"\"\\"", ",", "\"\\"", ",", "\"\\""}], "}"}]}], "]"}]}], ";", "\[IndentingNewLine]", " ", RowBox[{"loc", " ", "=", " ", RowBox[{"JSONElement", "[", RowBox[{"BotUserLocation", ",", RowBox[{"{", "fromid", "}"}]}], "]"}]}], ";", "\[IndentingNewLine]", RowBox[{"If", "[", RowBox[{ RowBox[{"loc", "===", "Null"}], ",", "\[IndentingNewLine]", RowBox[{"{", RowBox[{"True", ",", " ", RowBox[{"BotAnswerMsg", "[", RowBox[{ "msg", ",", " ", "\"\\"", ",", "bot"}], "]"}]}], "}"}], ",", "\[IndentingNewLine]", RowBox[{"{", RowBox[{"True", ",", " ", RowBox[{"BotAnswerMsg", "[", RowBox[{"msg", ",", " ", RowBox[{"ToString", "[", RowBox[{"WeatherData", "[", RowBox[{ RowBox[{ RowBox[{"{", RowBox[{"\"\\"", ",", "\"\\""}], "}"}], "/.", "loc"}], ",", "\"\\""}], "]"}], "]"}], ",", "bot"}], "]"}]}], "}"}]}], "\[IndentingNewLine]", "]"}]}]}], "\n", " ", "]"}]}]], "Input", InitializationCell->True], Cell["UnixTime is not defined in 10.0-. Let\[CloseCurlyQuote]s add \ compatibility:", "Text"], Cell[BoxData[ RowBox[{"If", "[", RowBox[{ RowBox[{"Not", "[", RowBox[{"NumberQ", "[", RowBox[{"UnixTime", "[", "]"}], "]"}], "]"}], ",", RowBox[{ RowBox[{"UnixTime", "[", "]"}], ":=", RowBox[{"Floor", "[", RowBox[{ RowBox[{"AbsoluteTime", "[", "]"}], "-", "2208988800", "-", RowBox[{"$TimeZone", "*", "3600"}]}], "]"}]}]}], "]"}]], "Input", InitializationCell->True], Cell["\<\ At the moment, the bot calls package provided functions BotErrorNoCmd, \ BotErrorUnknownCmd, BotErrorUnprivilegedCmd when errors occur. You can override them at will.\ \>", "Text"], Cell[BoxData[ RowBox[{ RowBox[{"BotErrorNoCmd", "[", RowBox[{"msg_", ",", "bot_"}], "]"}], ":=", RowBox[{"{", RowBox[{"True", ",", RowBox[{"BotAnswerMsg", "[", RowBox[{ "msg", ",", "\"\\"", ",", "bot"}], "]"}]}], "}"}]}]], "Input", InitializationCell->True], Cell["\<\ You can also override BotLog to change the way to see debug error (or \ suppress them)\ \>", "Text"], Cell[BoxData[ RowBox[{ RowBox[{"BotLog", "[", "str_", "]"}], ":=", RowBox[{"Print", "[", RowBox[{ RowBox[{"DateString", "[", "]"}], "<>", "\"\<: \>\"", "<>", "str"}], "]"}]}]], "Input", InitializationCell->True], Cell["\<\ Example of manually calling an API. Test this to see if your token works.\ \>", "Text"], Cell[BoxData[ RowBox[{"BotAPICall", "[", RowBox[{"\"\\"", ",", RowBox[{"{", "}"}], ",", RowBox[{"Import", "[", RowBox[{"$BotConfigFile", ",", "\"\\""}], "]"}]}], "]"}]], "Input"], Cell["\<\ To start the bot call BotStart. To stop it abort the evaluation.\ \>", "Text"], Cell[BoxData[ RowBox[{"BotStart", "[", RowBox[{"2", ",", " ", "$BotConfigFile", ",", " ", "$BotCmdList"}], "]"}]], "Input"] }, Open ]] }, WindowSize->{1920, 1007}, WindowMargins->{{186, Automatic}, {-129, 152}}, PrivateNotebookOptions->{"FileOutlineCache"->False}, TrackCellChangeTimes->False, FrontEndVersion->"11.0 for Linux x86 (64-bit) (September 21, 2016)", StyleDefinitions->"Default.nb" ]