Powershell 上 7-9 年級小學生最簡單的電報機器人模板

在與朋友的交談中,我突然發現,學校裡根本不教8-10年級的孩子編程。 Word、Excel 等等。 沒有徽標,甚至沒有 Pascal,甚至沒有 Excel 的 VBA。

我很驚訝,打開網絡爬了起來——
形象學校的任務之一是為新一代的教育做出貢獻,使其在發展水平和生活方式方面符合信息社會的條件。
本課程將在實踐中鞏固學生對 Pascal 編程語言基本結構的知識。 (摘自2017年部分體育館節目表)

因此,我決定花幾個小時草擬一個示例“如何為學童創建一個簡單的機器人”。

內容包括如何在 Powershell 中編寫另一個簡單的機器人,並使其在沒有 Webhook、白色 IP、專用服務器、雲中可部署虛擬機和其他東西的情況下在裝有常規 Windows 的普通家用 PC 上運行。

TLDR:又一篇無聊的文章,有語法和事實錯誤,沒有什麼可讀的,沒有幽默感,沒有圖片。

文章中沒有什麼新內容,之前寫的幾乎所有內容都已經在 Habré 上,例如在文章中 說明:如何在 Telegram 中創建機器人 и 系統管理員的 Telegram 機器人.
而且,這篇文章故意冗長,以免每次都引用教育文獻。 文本中沒有提及 gang 4、PowerShell Deep Dives 或 AWS Well-Architected Framework 的 5 個支柱。

您可以跳過前言,而不是

隨意跳過2006 年,微軟針對當時的 Windows XP、Vista 和 1.0 服務器發布了 PowerShell 2003。 在某些方面,它取代了 cmdbat 腳本、vb 腳本、Windows Script Host 和 JScript 等腳本。

即使是現在,PowerShell 也只能被認為是 Logo 選項之後的下一步,而不是 Delphi(或更舊的東西),儘管存在循環、類、函數、MS GUI 調用,但後者可能仍在某處使用, 與 Git 集成 等。

Powershell 使用得比較少,你只能以 PowerShell Core、VMware vSphere PowerCLI、Azure PowerShell、MS Exchange、Desired State Configuration 的形式遇到它, PowerShell 網絡訪問 以及十幾個很少使用的程序和功能。 也許隨著發布他會重獲新生 世界超級聯賽2,但不完全是這樣。

Powershell還具有三大優點:

  1. 它相對簡單,有很多關於它的文獻和例子,甚至在俄語中,例如,一篇關於 Foreach 的文章來自這本書 深入了解 PowerShell - 關於 () 和 {} 的區別
  2. 它帶有一個編輯器 ISE,與 Windows 捆綁在一起。 甚至還有某種調試器。
  3. 從它很容易調用 用於構建圖形界面的組件.

0.準備。

我們將需要:

  • Windows 電腦(我有 Windows 10)
  • 至少某種 Internet 訪問(例如通過 NAT)
  • 對於那些對電報訪問權限有限的人 - 在瀏覽器中安裝和配置 freegate,在某些困難的情況下,與 Symple DNS Crypt 一起使用
  • 電話上存在正在運行的電報客戶端
  • 了解最基本的知識——什麼是變量、數組、循環。

打開並閱讀文章 - 說明:如何在 Telegram 中創建機器人 и 系統管理員的 Telegram 機器人

1. 讓我們創建另一個測試機器人。

既然大家都知道了,而且已經發生了,你也可以跳過正如上面的文章所述 – 首先,一個 Telegram 機器人 – 它仍然是一個在您這邊運行的應用程序,向 Telegram Bot API 發出請求。 此外,API 是可以理解的 - 機器人使用參數訪問特定的 URL,Telegram 使用 JSON 對象進行響應。

相關問題:如果您以某種未知的方式從 JSON 對像中獲取一些代碼並以某種方式將其發送以執行(不是故意的),則該代碼將為您執行。

上面兩篇文章描述了創建過程,但我重複一遍:在電報中,打開聯繫人,尋找@botfather,告訴他/newbot,創建一個Botfortest12344321機器人,我們稱之為Mynext1234bot,並獲取帶有唯一密鑰的消息像 1234544311:AbcDefNNNNNNNNNNNN

保管好鑰匙,不要洩露出去!

然後您可以配置機器人,例如禁止將其添加到組中,但這在第一步中不是必需的。

如果我們不喜歡某些內容,請詢問 BotFather“/mybot”並修復設置。

再次打開聯繫人,在那裡找到@Botfortest12344321(搜索必須以@開頭),單擊“開始”並向機器人寫入“/Glory to the robots”。 / 是必需的,不需要引號。
當然,機器人不會回答任何問題。

讓我們檢查一下機器人是否已創建 - 打開它。

api.telegram.org/bot1234544311:AbcDefNNNNNNNNNNNN/getMe
其中 1234544311:AbcDefNNNNNNNNNNNN 是之前獲得的密鑰,
並得到一行像
{“確定”:true,“結果”:{“”}}

我們有第一個秘密短語(令牌)。 現在我們需要找出第二個秘密數字 - 與機器人的聊天 ID。 每個聊天、群組等都是單獨的,並且有自己的號碼(有時對於開放群組帶有減號)。 為了找到這個數字,我們需要在瀏覽器中請求(事實上,在瀏覽器中根本沒有必要,但是為了更好地理解你可以從它開始)地址(其中 1234544311:NNNNNNNN 是你的令牌

https://api.telegram.org/bot1234544311:NNNNNNNNN/getUpdates

並得到類似的回應

{“確定”:true,“結果”:[{“update_id”:…,… 館員諮詢“:{“ID”:123456789

我們確實需要 chat_id。

讓我們檢查一下是否可以手動寫入聊天:從瀏覽器調用該地址

https://api.telegram.org/botваштокен/sendMessage?chat_id=123456789&text="Life is directed motion"

如果您在聊天中收到來自機器人的消息 - 好的,您可以進入下一步。

因此(通過瀏覽器)您始終可以檢查問題出在哪裡 - 生成鏈接時遇到的問題,或者某處的某些內容被掩蓋並且不起作用。

繼續閱讀之前您需要了解什麼

Telegram 有多種類型的群聊(開放式、封閉式)。 對於這些聊天,某些功能(例如id)是不同的,這有時會導致一些問題。

我們假設現在是 2019 年底,甚至我們這個時代的英雄、著名的 Man-Orchestra(管理員、律師、信息安全官、程序員和實際上的 MVP)Evgeny V. 也將 $i 變量與數組,已經掌握了循環,你看起來在接下來的幾年裡將掌握巧克力,並且在那裡 使用 PowerShell 並行處理 и ForEach-對象並行 將會來。

1.我們認為我們的機器人會做什麼

我沒有想法,我必須思考。 我已經寫了一個機器人筆記本。 我不想製作一個“向某個地方發送東西”的機器人。 要連接 Azure,您需要一張信用卡,但學生從哪裡獲得信用卡呢? 應該指出的是,一切都還不錯:主要的雲免費提供某種測試期(但你仍然需要信用卡號 - 並且會從中扣除,似乎是一美元。我不記得了如果他稍後回來的話。)

如果沒有人工智能機器學習,製作一個白痴詩歌機器人就沒那麼有趣了。

我決定製作一個機器人,它可以提醒我(或不提醒我)字典中的英語單詞。
為了不弄亂數據庫,字典將位於文本文件中並手動補充。
在這種情況下,任務是展示工作中的基礎知識,而不是至少製作部分成品。

2. 第一次嘗試什麼以及如何嘗試

創建文件夾 C:poshtranslate
首先我們看看我們有什麼樣的powershell,通過start-run運行ISE
powershell 伊勢
或者在已安裝的程序中找到 Powershell ISE。
啟動後,通常熟悉的“某種編輯器”將打開,如果沒有文本字段,那麼您可以隨時單擊“文件 - 新建”。

讓我們看看 powershell 版本 - 在文本字段中寫入:

get-host 

並按 F5。

Powershell 將提供保存 - “您將要運行的腳本將被保存。”,我們同意,並將文件從 powershell 保存在 C: poshtranslate 中,名稱為 poshtranslate myfirstbotBT100.

啟動後,在下方的文本框中我們得到一個數據板:

Name             : Windows PowerShell ISE Host
Version          : 5.1.(и так далее)

我有5.1的東西,這就足夠了。 如果您有舊的 Windows 7/8,那麼沒關係 - 儘管 PowerShell 需要更新到版本 5 - 例如, 路線.

在下面的命令行中輸入Get-Date,回車,看一下時間,用命令進入根文件夾
cd
並使用 cls 命令清除屏幕(不,您不需要使用 rm)

現在讓我們檢查一下什麼有效以及如何工作 - 讓我們不寫代碼,而是寫兩行,並嘗試理解它們的作用。 讓我們用 get-host 符號 # 註釋掉該行並添加一些內容。

# Пример шаблона бота 
# get-host
<# это пример многострочного комментария #>
$TimeNow = Get-Date
$TimeNow

(有趣。Habré 的代碼設計下拉列表中有兩打選項 - 但 powershell 不在那裡。Dos 是。Perl 是。)

並通過在 GUI 中按 F5 或“>”來運行代碼。

我們得到輸出:

Saturday, December 8, 2019 21:00:50 PM (или что-то типа)

現在讓我們處理這兩行以及一些有趣的點,以免將來不再討論這一點。

與 Pascal 不同(而且不僅如此),powershell 本身會嘗試確定分配給變量的類型,有關此內容的更多信息請參閱文章 關於編程語言輸入的教育計劃
因此,通過設置 $TimeNow 變量並將當前日期和時間的值(Get-Date)分配給它,我們不必太擔心其中的數據類型。

誠然,這種無知可能會造成傷害,但那是後來的事了。 下面是文中的一個例子。
讓我們看看我們得到了什麼。 執行(在命令行上)

$TimeNow | Get-member

並得到一頁難以理解的文字

難以理解的文本編號 1 的示例

PS C:> $TimeNow | Get-member
   TypeName: System.DateTime
Name                 MemberType     Definition                                                                                                                                       
----                 ----------     ----------                                                                                                                                       
Add                  <b>Method         </b>datetime Add(timespan value)  
..
DisplayHint          NoteProperty   DisplayHintType DisplayHint=DateTime                                                                                                             
Date                 <b>Property       </b>datetime Date {get;}                                                                                                                             
Year                 Property       int Year {get;}   
..                                                                                                                               
DateTime             ScriptProperty System.Object DateTime {get=if ((& { Set-StrictMode -Version 1; $this.DisplayHint }) -ieq  "Date")...                                         

正如您所看到的,已使用一堆方法(從我們可以使用此變量對象執行的操作的意義上來說)和屬性創建了 TypeName: System.DateTime 類型的變量。

我們打電話吧 $TimeNow.DayOfYear - 獲取一年中的第幾天。
我們打電話吧 $TimeNow.DayOfYear | Get-Member - 得到 TypeName: System.Int32 和一組方法。
我們打電話吧 $TimeNow.ToUniversalTime() - 並獲取 UTC 時間

調試器

有時,您需要執行程序到某一行並查看該時刻程序的狀態。 為此,ISE 有一個調試功能 - 切換斷點
在中間某處放置一個斷點,運行這兩行,看看斷點是什麼樣的。

3. 了解與 Telegram 機器人的交互

當然,關於與機器人交互、與所有 getpush 等交互的文獻已經有更多,但理論問題可以被認為是可選的。

在我們的例子中,我們需要:

  • 學會發送一些東西到信件
  • 學會從信件中得到一些東西

3.1 學習發送郵件並從中接收郵件

一些代碼 - 第 3 部分

Write-output "This is part 3"
$MyToken = "1234544311:AbcDefNNNNNNNNNNNNN"
$MyChatID = "123456789"
$MyProxy = "http://1.2.3.4:5678" 

$TimeNow = Get-Date
$TimeNow.ToUniversalTime()
$ScriptDir = Split-Path $script:MyInvocation.MyCommand.Path
$BotVersion = "BT102"

$MyText01 = "Life is directed motion - " + $TimeNow

$URL4SEND = "https://api.telegram.org/bot$MyToken/sendMessage?chat_id=$MyChatID&text=$MyText01"

Invoke-WebRequest -Uri $URL4SEND

在 RF 中,我們收到錯誤“無法連接到遠程服務器”。

或者我們不明白 - 這取決於電信運營商以及代理是否已配置並正常工作
好吧 - 仍然需要添加代理。 請注意 - 使用未加密且通常保留的代理對您的健康極其危險。

尋找可用代理的任務並不是很困難 - 大多數已發布的 http 代理都可以工作。 這似乎連續第五次對我有用。

使用代理的語法:

Invoke-WebRequest -Uri $URL4SEND -Proxy $MyProxy

如果您在與機器人的聊天中收到一條消息,那麼一切都很好,您可以繼續。 如果沒有,繼續調試。

您可以查看 $URL4SEND 字符串變成什麼,並嘗試在瀏覽器中請求它,如下所示:

$URL4SEND2 = '"'+$URL4SEND+'"'
start chrome $URL4SEND2 

3.2. 我們已經學會了在聊天中寫“東西”,現在我們將嘗試閱讀

讓我們再添加 4 行,通過 | 看看裡面有什麼。 獲取會員

$URLGET = "https://api.telegram.org/bot$MyToken/getUpdates"
$MyMessageGet = Invoke-WebRequest -Uri $URLGET -Method Get -Proxy $MyProxy
Write-Host "Get-Member"
$MyMessageGet | Get-Member

最有趣的是給我們

Content           Property   string Content {get;}  
ParsedHtml        Property   mshtml.IHTMLDocument2 ParsedHtml {get;}                                    
RawContent        Property   string RawContent {get;set;}

讓我們看看它們裡面有什麼:

Write-Host "ParsedHtml"
$MyMessageGet.ParsedHtml # тут интересное
Write-Host "RawContent"
$MyMessageGet.RawContent # и тут интересное, но еще к тому же и читаемое. 
Write-Host "Content"
$MyMessageGet.Content

如果一切順利,你會得到一條長隊,例如:

{"ok":true,"result":[{"update_id":12345678,
"message":{"message_id":3,"from":{"id"

幸運的是,在之前發表的文章《Telegram bot for the systemadministrator》中,這一行(是的,根據 $MyMessageGet.RawContent | get-member 是 System.String)已經被拆除了。

4. 處理收到的內容(我們至少已經知道如何發送一些東西)

正如已經寫過的 這裡,最必要的在於內容。 讓我們更仔細地看一下。

首先,讓我們從網絡界面或電話中向機器人編寫更多短語

/message1
/message2
/message3

並通過瀏覽器查看 $URLGET 變量中生成的地址。

我們會看到類似的東西:

{"ok":true,"result":[{"update_id":NNNNNNN,
"message":{"message_id":10, .. "text":"/message1"
"message":{"message_id":11, .. "text":"/message2 
"message":{"message_id":12, .. "text":"/message3 

這是什麼? 一些複雜的對象來自包含消息標識符、聊天標識符、調度標識符和大量信息的對像數組。

然而,我們不需要分析“這是什麼類型的物體”——部分工作已經為我們完成了。 讓我們看看裡面有什麼:

閱讀收到的消息或第 4 部分

Write-Host "This is part 4" <# конечно эта строка нам не нужна в итоговом тексте, но по ней удобно искать. #> 

$Content4Pars01 = ConvertFrom-Json $MyMessageGet.Content
$Content4Pars01 | Get-Member
$Content4Pars01.result
$Content4Pars01.result[0]
$Content4Pars01.result[0] | Get-Member
$Content4Pars01.result[0].update_id
$Content4Pars01.result[0].message
$Content4Pars01.result[0].message.text
$Content4Pars01.result[1].message.text
$Content4Pars01.result[2].message.text

5.我們現在用它做什麼

將生成的文件保存為 myfirstbotBT105 或任何您喜歡的名稱,更改標題並註釋掉所有已編寫的代碼

<#start comment 105 end comment 105#>

現在我們需要決定從哪裡獲取字典(好吧,在哪裡 - 在磁盤上的文件中)以及它的外觀。

當然,你可以在腳本的文本中填入一本巨大的字典,但事實並非如此。
因此,我們來看看powershell可以正常使用什麼。
事實上,他並不關心使用什麼文件,我們也不關心。
我們有一個選擇:txt(這是可能的,但為什麼)、csv、xml。
你可以看到每個人 讓我們看看每個人。
創建類 MyVocabClassExample1 和變量 $MyVocabExample1
我注意到該類的編寫沒有 $

一些代碼#5

write-host "This is part 5"
class MyVocabClassExample1 {
    [string]$Original  # слово
    [string]$Transcript
    [string]$Translate
    [string]$Example
    [int]$VocWordID # очень интересный момент. Использование int с его ограничениями может порой приводить к диким последствиям, для примера - недавний случай с SSD HPE. Изначально я не стал добавлять этот элемент, потом все же дописал и закомментировал.
    }

$MyVocabExample1 = [MyVocabClassExample1]::new()
$MyVocabExample1.Original = "Apple"
$MyVocabExample1.Transcript = "[ ˈapəl ]"
$MyVocabExample1.Translate = "Яблоко"
$MyVocabExample1.Example = "An apple is a sweet, edible fruit produced by an apple tree (Malus domestica)"
# $MyVocabExample1.$VocWordID = 1

$MyVocabExample2 = [MyVocabClassExample1]::new()
$MyVocabExample2.Original = "Pear"
$MyVocabExample2.Transcript = "[ pe(ə)r ]"
$MyVocabExample2.Translate = "Груша"
$MyVocabExample2.Example = "The pear (/ˈpɛər/) tree and shrub are a species of genus Pyrus"
# $MyVocabExample1.$VocWordID = 2

讓我們嘗試將其寫入文件 模範.

一些代碼#5.1

Write-Host $ScriptDir # надеюсь $ScriptDir вы не закомментировали 
$MyFilenameExample01 = $ScriptDir + "Example01.txt"
$MyFilenameExample02 = $ScriptDir + "Example02.txt"
Write-Host $MyFilenameExample01
Out-File  -FilePath $MyFilenameExample01 -InputObject $MyVocabExample1

Out-File  -FilePath $MyFilenameExample01 -InputObject -Append $MyVocabExample2
notepad $MyFilenameExample01

- 並在 Out-File -FilePath $MyFilenameExample01 -InputObject -Append $MyVocabExample2 行上收到錯誤。

不想補充了,唉,可惜了。

$MyVocabExample3AsArray = @($MyVocabExample1,$MyVocabExample2)
Out-File  -FilePath $MyFilenameExample02 -InputObject $MyVocabExample3AsArray
notepad $MyFilenameExample02

讓我們來看看發生了什麼。 漂亮的文本視圖 - 但如何從它導出回來? 輸入某種文本分隔符,例如逗號?

結果,得到一個“帶有分隔符的文件 - 逗號,逗號分隔值(CSV)A 停止等待.
#

$MyFilenameExample03 = $ScriptDir + "Example03.csv"
$MyFilenameExample04 = $ScriptDir + "Example04.csv"
Export-Csv  -Path $MyFilenameExample03 -InputObject $MyVocabExample1 
Export-Csv  -Path $MyFilenameExample03 -InputObject $MyVocabExample2 -Append 
Export-Csv  -Path $MyFilenameExample04 -InputObject $MyVocabExample3AsArray 

不難看出,MS在邏輯上並沒有特別區分,對於類似的過程,一種情況使用-FilePath,另一種情況使用-Path。

此外,俄語在第三個文件中消失了,在第四個文件中事實證明......好吧,發生了一些事情。 #TYPE 系統對象[] 00
# "Count","Length","LongLength","Rank","SyncRoot","IsReadOnly","IsFixedSize","IsSynchronized"
#
讓我們重寫一下:

Export-Csv  -Path $MyFilenameExample03 -InputObject $MyVocabExample1 -Encoding Unicode
Export-Csv  -Path $MyFilenameExample03 -InputObject $MyVocabExample2 -Append -Encoding Unicode
notepad $MyFilenameExample03
notepad $MyFilenameExample04

這似乎有幫助,但我仍然不喜歡這種格式。

我特別不喜歡的是我不能將對像中的行直接放入文件中。
順便說一句,既然我們開始寫入文件,我們可以開始記錄啟動嗎? 我們有時間作為變量,我們可以設置文件名。

確實,還沒有什麼可寫的,但是您可以考慮如何最好地進行日誌輪換。
現在讓我們嘗試一下 xml。

一些 XML

$MyFilenameExample05 = $ScriptDir + "Example05.xml"
$MyFilenameExample06 = $ScriptDir + "Example06.xml"
Export-Clixml  -Path $MyFilenameExample05 -InputObject $MyVocabExample1 
Export-Clixml  -Path $MyFilenameExample05 -InputObject $MyVocabExample2 -Append -Encoding Unicode
Export-Clixml  -Path $MyFilenameExample06 -InputObject $MyVocabExample3AsArray
notepad $MyFilenameExample05
notepad $MyFilenameExample06

導出到 xml 具有堅實的優勢 - 可讀性、導出整個對像以及無需執行 uppend。

讓我們嘗試 讀取xml文件.

從 xml 讀取一些內容

$MyFilenameExample06 = $ScriptDir + "Example06.xml"
$MyVocabExample4AsArray = Import-Clixml -Path $MyFilenameExample06
# $MyVocabExample4AsArray 
# $MyVocabExample4AsArray[0]
# и немного о совершенно неочевидных нюансах. Powershell время от времени ведет себя не так, как вроде бы как бы стоило бы ожидать бы.
# например у меня эти два вывода отличаются
# Write-Output $MyVocabExample4AsArray 
# write-host $MyVocabExample4AsArray 

讓我們回到任務上來。 我們寫了一個測試文件,讀一下,存儲格式就明白了,如果有需要,可以寫一個單獨的小文件編輯器來添加和刪除行。

讓我提醒您,任務是製作一個小型訓練機器人。

工作格式:我向機器人發送“示例”命令,機器人向我發送隨機選擇的單詞和轉錄,10 秒後它發送翻譯和評論。 我們知道如何讀取命令,當然,還學習如何自動選擇和檢查代理,並將消息計數器重置為遺忘。

讓我們取消之前註釋掉的所有不必要的註釋,註釋掉不必要的 txt 和 csv 示例,並將文件另存為版本 B106

是啊。 讓我們再次向機器人發送一些東西。

6. 從函數發送等

在處理接收之前,需要製作發送“至少有一些東西”的功能,測試消息除外。

當然,在示例中我們只有一次發送和一次處理,但是如果我們需要多次執行同一操作怎麼辦?

寫一個函數更容易。 因此,我們有一個 $MyVocabExample4AsArray 對像類型的變量,從文件中讀取,作為兩個完整元素的數組。
我們去讀書吧。

同時,我們將處理時鐘,稍後我們會需要它(事實上,在這個例子中,我們不會需要它)

一些代碼#6.1

Write-Output "This is Part 6"
$Timezone = (Get-TimeZone)
IF($Timezone.SupportsDaylightSavingTime -eq $True){
    $TimeAdjust =  ($Timezone.BaseUtcOffset.TotalSeconds + 3600) } # приведенное время
    ELSE{$TimeAdjust = ($Timezone.BaseUtcOffset.TotalSeconds) 
    }
    
function MyFirstFunction($SomeExampleForFunction1){
$TimeNow = Get-Date
$TimeNow.ToUniversalTime()
# $MyText02 = $TimeNow + " " + $SomeExampleForFunction1 # и вот тут мы получим ошибку
$MyText02 = $SomeExampleForFunction1 + " " + $TimeNow # а тут не получим, кто догадается почему - тот молодец.

$URL4SendFromFunction = "https://api.telegram.org/bot$MyToken/sendMessage?chat_id=$MyChatID&text=$MyText02"
Invoke-WebRequest -Uri $URL4SendFromFunction -Proxy $MyProxy
}

正如您所看到的,函數中調用了 $MyToken 和 $MyChatID,這兩個值是之前硬編碼的。

您不需要這樣做,如果每個機器人都有一個 $MyToken,那麼 $MyChatID 將根據聊天而變化。

但是,由於這是一個示例,因此我們暫時忽略它。

由於 $MyVocabExample4AsArray 不是數組,儘管它非常相似,那麼 你不能只是拿 詢問其長度。

我們將再次不得不做不能做的事情 - 不按照代碼跳傘 - 拍攝和計數

一些代碼#6.2

$MaxRandomExample = 0 
foreach ($Obj in $MyVocabExample4AsArray) {
$MaxRandomExample ++
}
Write-Output $MaxRandomExample
$RandomExample = Get-Random -Minimum 0 -Maximum ($MaxRandomExample)
$TextForExample1 = $MyVocabExample4AsArray[$RandomExample].Original
# MyFirstFunction($TextForExample1)
# или в одну строку
# MyFirstFunction($MyVocabExample4AsArray[Get-Random -Minimum 0 -Maximum ($MaxRandomExample -1)].Example)
# Угадайте сами, какой пример легче читается посторонними людьми.

隨機 有趣的功能。 假設我們想要接收 0 或 1(數組中只有兩個元素)。 當設置邊界 0..1 時 - 我們會得到“1”嗎?
不 - 我們不會得到它,我們專門給出了一個例子 示例 2:獲取 0 到 99 之間的隨機整數 Get-Random -Maximum 100
因此,對於0..1,我們需要將大小設置為0..2,而最大元素數=1。

7.傳入消息的處理和隊列的最大長度

我們之前停在哪裡? 我們有一個接收到的變量 $MyMessageGet
以及從中獲得的 $Content4Pars01,從中我們對數組 Content4Pars01.result 的元素感興趣

$Content4Pars01.result[0].update_id
$Content4Pars01.result[0].message
$Content4Pars01.result[0].message.text

讓我們向機器人發送 /message10、/message11、/message12、/word,然後再次發送 /word 和 /hello。
讓我們看看我們得到了什麼:

$Content4Pars01.result[0].message.text
$Content4Pars01.result[2].message.text

讓我們迭代收到的所有內容,如果消息是 / word 則發送響應
構造的情況,有些人稱之為 if-elseif,在 powershell 中被稱為 通過開關。 同時,下面的代碼中使用了-wildcard鍵,這是完全沒有必要的,甚至是有害的。

一些代碼#7.1

Write-Output "This is part 7"
Foreach ($Result in $Content4Pars01.result) # Да, можно сделать быстрее 
 { 
    switch -wildcard ($Result.message.text) 
            {
            "/word" {MyFirstFunction($TextForExample1)}
            }
}

讓我們運行該腳本幾次。 每次執行嘗試時,我們都會得到相同的單詞兩次,特別是如果我們在隨機實現中犯了錯誤。

但停下來。 我們沒有再次發送/word,為什麼消息又被處理了?

向機器人發送消息的隊列的長度是有限的(我認為是 100 或 200 條消息),並且必須手動清除它。

當然,文檔中對此有描述,但還是有必要閱讀一下!

在這種情況下,我們需要 ?chat_id 參數,並且還不需要 &timeout、&limit、&parse_mode=HTML 和 &disable_web_page_preview=true。

文檔 電報 API 在這裡
上面用英文和白字寫著:
要返回的第一個更新的標識符。 必須比先前收到的更新的標識符中的最高標識符大一。 默認情況下,從最早的開始更新
未經證實 更新被返回。 一旦使用 getUpdates 調用,更新就被視為已確認 抵消 更高 比它的 update_id。 可以指定負偏移量以檢索從更新隊列末尾的 -offset update 開始的更新。 所有以前的更新都將被忘記。

讓我們看看:

$Content4Pars01.result[0].update_id
$Content4Pars01.result[1].update_id 
$Content4Pars01.result | select -last 1
($Content4Pars01.result | select -last 1).update_id

是的,讓我們重置 - 我們將稍微重寫該函數。 我們有兩個選擇 - 將整個消息傳遞給函數並在函數中完全處理它,或者僅給出消息 ID 並丟棄它。 例如,第二個看起來更簡單。

以前,我們的“所有消息”查詢字符串看起來像

$URLGET = "https://api.telegram.org/bot$MyToken/getUpdates"

它看起來像

$LastMessageId = ($Content4Pars01.result | select -last 1).update_id
$URLGET1 = "https://api.telegram.org/bot$mytoken/getUpdates?offset=$LastMessageId&limit=100" 
$MyMessageGet = Invoke-WebRequest -Uri $URLGET1 -Method Get -Proxy $MyProxy 

沒有人禁止您首先接收所有消息並處理它們,並且只有在成功處理請求未確認 -> 確認後。

為什麼在所有處理完成後調用確認才有意義? 它可能會在執行過程中失敗,如果以免費聊天機器人為例,跳過一條消息仍然沒什麼特別的,那麼如果您正在處理某人的工資或卡交易,那麼結果可能會更糟。

多幾行代碼

$LastMessageId = ($Content4Pars01.result | select -last 1).update_id  #ошибку в этом месте предполагается исправить самостоятельно. 
$URLGET1 = "https://api.telegram.org/bot$mytoken/getUpdates?offset=$LastMessageId&limit=100" 
Invoke-WebRequest -Uri $URLGET1 -Method Get -Proxy $MyProxy

8. 代替結論

主要功能 - 讀取消息、刷新隊列、從文件讀取和寫入文件均已完成並顯示。

只剩下四件事要做:

  • 在聊天中發送請求的正確答案
  • 向添加了機器人的任何聊天發送響應
  • 在循環中執行代碼
  • 從 Windows 調度程序啟動機器人。

所有這些任務都很簡單,通過閱讀有關參數的文檔即可輕鬆實現,例如
Set-ExecutionPolicy Unrestricted 和 -ExecutionPolicy Bypass
形式的循環

$TimeToSleep = 3 # опрос каждые 3 секунды
$TimeToWork = 10 # минут
$HowManyTimes = $TimeToWork*60/$TimeToSleep # счетчик для цикла
$MainCounter = 0
for ($MainCounter=0; $MainCounter -le $HowManyTimes) {
sleep $TimeToSleep
$MainCounter ++

感謝所有閱讀的人。

來源: www.habr.com

添加評論