Șablon pentru un robot telegram simplu pentru școlari din clasele 7-9 folosind Powershell

În timpul conversațiilor cu un prieten, am aflat brusc că copiii din clasele 8-10 de la școala lor nu sunt învățați deloc programarea. Word, Excel și tot. Fără logo, nici măcar Pascal, nici măcar VBA pentru Excel.

Am fost foarte surprins, am deschis internetul și am început să citesc -
Una dintre sarcinile unei școli de specialitate este promovarea educației unei noi generații care să îndeplinească condițiile societății informaționale în nivelul ei de dezvoltare și stil de viață.
Acest curs va permite studenților să-și consolideze în practică cunoștințele despre constructele de bază ale limbajului de programare Pascal. (din programul unor gimnazii pe anul 2017)

În cele din urmă, am decis să petrec câteva ore și să schițez un exemplu despre „cum să creez un robot simplu pentru școlari”.

Mai jos este cum să scrieți un alt bot simplu în Powershell și să îl faceți să funcționeze fără un webhook, IP-uri albe, servere dedicate, mașini virtuale implementate în cloud și așa mai departe - pe un computer de acasă obișnuit cu Windows obișnuit.

TLDR: Un alt articol plictisitor cu erori gramaticale și faptice, nimic de citit, fără umor, fără poze.

Nu este nimic nou în articol, aproape tot ce s-a scris înainte a fost deja pe Habré, de exemplu în articole Instrucțiuni: Cum să creați boți în Telegram и Bot Telegram pentru administratorul de sistem.
Mai mult, articolul este în mod voit redundant pentru a nu face referire de fiecare dată la literatura educațională. În text nu există referințe la Gang 4, PowerShell Deep Dives sau, să zicem, Cei 5 piloni ai AWS Well-Architected Framework.

În loc de o prefață, puteți sări peste

Simțiți-vă liber să săriți pesteÎn 2006, Microsoft a lansat PowerShell 1.0 pentru Windows XP, Vista și Server 2003 de atunci. În unele moduri, a înlocuit lucruri precum scripturile cmdbat, scripturile vb, Windows Script Host și JScript.

Chiar și acum, PowerShell poate fi considerat doar pasul următor după opțiunile Logo, în loc de Delphi probabil încă folosit (sau ceva mai vechi), în ciuda prezenței buclelor, claselor, funcțiilor, apelurilor MS GUI, Integrare Git și așa mai departe.

Powershell este folosit relativ rar, îl puteți întâlni doar sub formă de PowerShell Core, VMware vSphere PowerCLI, Azure PowerShell, MS Exchange, Desired State Configuration, Acces Web PowerShell și vreo duzină de programe și funcții mai rar utilizate. Poate că va primi un al doilea vânt odată cu eliberarea WSL2, dar nu este exact.

Powershell are, de asemenea, trei mari avantaje:

  1. Este relativ simplu, există multă literatură și exemple despre asta și chiar și în rusă, de exemplu, un articol despre Foreach - din carte PowerShell în profunzime - despre diferența () și {}
  2. Merge cu redactorul ISE, inclus cu Windows. Există chiar și un fel de depanator acolo.
  3. Este ușor să suni de la ea componente pentru construirea unei interfeţe grafice.

0. Pregătirea.

Vom avea nevoie de:

  • PC Windows (am Windows 10)
  • Cel puțin un fel de acces la Internet (prin NAT de exemplu)
  • Pentru cei care au acces limitat la telegram - freegate instalat și configurat în browser, în unele cazuri dificile, împreună cu Symple DNS Crypt
  • Aveți un client Telegram funcțional pe telefon
  • Înțelegerea elementelor de bază - ce este o variabilă, o matrice, o buclă.

Articole deschise și citite - Instrucțiuni: Cum să creați boți în Telegram и Bot Telegram pentru administratorul de sistem

1. Să creăm un alt bot de testare.

Deoarece toată lumea știe deja acest lucru și s-a întâmplat deja, puteți sări peste elDupă cum se spune în articolul de mai sus - În primul rând, un bot pentru Telegram - este încă o aplicație care rulează de partea ta și care face solicitări către API-ul Telegram Bot. Mai mult, API-ul este clar - botul accesează o anumită adresă URL cu parametri, iar Telegram răspunde cu un obiect JSON.

Probleme înrudite: dacă într-un fel necunoscut luați un cod dintr-un obiect JSON și îl trimiteți cumva spre execuție (nu intenționat), codul va fi executat pentru dvs.

Procesul de creare este descris în două articole de mai sus, dar repet: într-o telegramă deschidem contacte, căutăm @botfather, îi spunem /newbot, creăm un bot Botfortest12344321, îl numim Mynext1234bot și primim un mesaj cu o cheie unică a lui. formularul 1234544311:AbcDefNNNNNNNNNNNNNN

Ai grijă de cheie și nu o da!

Apoi puteți configura botul, de exemplu, interziceți adăugarea lui la grupuri, dar în primii pași acest lucru nu este necesar.

Să-i cerem lui BotFather „/mybot” și să ajustem setările dacă nu ne place ceva.

Să deschidem din nou contactele, găsim acolo @Botfortest12344321 (este obligatoriu să începeți căutarea cu @), faceți clic pe „start” și scrieți botului „/Glory to the robots”. Semnul / este obligatoriu, nu sunt necesare ghilimele.
Botul, desigur, nu va răspunde la nimic.

Să verificăm dacă botul a fost creat și să îl deschidem.

api.telegram.org/bot1234544311:AbcDefNNNNNNNNNNNNNN/getMe
unde 1234544311:AbcDefNNNNNNNNNNNNNN este cheia primită anterior,
și obțineți o linie ca
{"ok":true,"result":{""}}

Avem prima frază secretă (token). Acum trebuie să aflăm al doilea număr secret - ID-ul chat-ului cu botul. Fiecare chat, grup etc. este individual și are propriul său număr (uneori cu minus - pentru grupuri deschise). Pentru a afla acest număr, trebuie să solicităm în browser (de fapt, nu este deloc necesar în browser, dar pentru o mai bună înțelegere poți începe cu el) adresa (unde 1234544311:NNNNNNNNNN este tokenul tău).

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

și obțineți un răspuns ca

{"ok":true,"result":[{"update_id":...,... Chat":{"id":123456789

Avem nevoie de chat_id.

Să verificăm că putem scrie manual pe chat: apelați adresa din browser

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

Dacă primești un mesaj de la un bot în chatul tău, bine, treci la etapa următoare.

Astfel (prin browser) puteți verifica oricând dacă există probleme cu generarea link-ului sau dacă ceva este ascuns undeva și nu funcționează.

Ce trebuie să știți înainte de a continua lectura

Telegram are mai multe tipuri de chat-uri de grup (deschise, închise). Pentru aceste chat-uri, unele dintre funcții (de exemplu, id) sunt diferite, ceea ce uneori provoacă unele probleme.

Să presupunem că este sfârșitul anului 2019 și chiar și eroul timpului nostru, binecunoscuta Man-Orchestra (administrator, avocat, specialist în securitatea informațiilor, programator și practic MVP) Evgeniy V. distinge variabila $i de o matrice, a stăpânit buclele, uite în următorii doi ani va stăpâni Chocolatey, și apoi Procesare paralelă cu PowerShell и Pentru fiecare obiect paralel va veni.

1. Ne gândim la ce va face botul nostru

Nu aveam idei, trebuia să mă gândesc. Am scris deja un caiet-bot. Nu am vrut să fac un bot „care trimite ceva undeva”. Pentru a vă conecta la Azure aveți nevoie de un card de credit, dar de unde îl obține studentul? Trebuie remarcat că totul nu este atât de rău: norii principali dau un fel de perioadă de testare gratuit (dar încă ai nevoie de un număr de card de credit - și se pare că un dolar va fi debitat din el. Nu-mi amintesc dacă a fost returnat mai târziu.)

Fără AI ML nu este atât de interesant să faci un bot-sărac-poet-țesător.

Am decis să fac un bot care să-mi amintească (sau nu) de cuvintele englezești din dicționar.
Pentru a evita manipularea bazei de date, dicționarul va fi stocat într-un fișier text și actualizat manual.
În acest caz, sarcina este de a arăta elementele de bază ale lucrării și nu de a realiza cel puțin un produs parțial finit.

2. Încercați ce și cum pentru prima dată

Să creăm un folder C:poshtranslate
Mai întâi, să vedem ce fel de powershell avem, să lansăm ISE prin start-run
puterea este
sau găsiți Powershell ISE în programele instalate.
După lansare, se va deschide obișnuitul „un fel de editor” dacă nu există un câmp de text, atunci puteți face oricând clic pe „Fișier - creați nou”.

Să ne uităm la versiunea de powershell - scrieți în câmpul de text:

get-host 

și apăsați F5.

Powershell va oferi să salveze - „Scriptul pe care urmează să-l rulați va fi salvat.”, suntem de acord și salvăm fișierul din powershell cu numele în C: poshtranslate myfirstbotBT100.

După lansare, în fereastra de text inferioară obținem un tabel de date:

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

Am 5.1 ceva, e suficient. Dacă aveți un Windows 7/8 vechi, atunci nu este mare lucru - deși PowerShell va trebui actualizat la versiunea 5 - de ex. instrucțiuni.

Tastați Get-Date în linia de comandă de mai jos, apăsați Enter, uitați-vă la ora, mergeți la folderul rădăcină cu comanda
cd
și ștergeți ecranul cu comanda cls (nu, nu trebuie să utilizați rm)

Acum să verificăm ce funcționează și cum - să scriem nici măcar codul, ci două linii și să încercăm să înțelegem ce fac. Să comentăm linia cu get-host cu simbolul # și să adăugăm puțin.

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

(Ceea ce este interesant este că în lista derulantă de formatare a codului de pe Habré există două duzini de opțiuni - dar Powershell nu este acolo. Dos este acolo. Perl este acolo.)

Și să rulăm codul apăsând F5 sau „>” din GUI.

Obținem următoarea ieșire:

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

Acum să ne uităm la aceste două rânduri și la câteva puncte interesante, astfel încât să nu revenim la asta în viitor.

Spre deosebire de Pascal (și nu numai), PowerShell însuși încearcă să determine ce tip să atribuie unei variabile mai multe detalii despre aceasta sunt scrise în articol Program educativ despre tastarea în limbaje de programare
Prin urmare, prin crearea unei variabile $TimeNow și alocarea acesteia cu valoarea datei și orei curente (Get-Date), nu trebuie să ne îngrijorăm prea mult cu privire la tipul de date care vor fi acolo.

Adevărat, această ignoranță poate răni mai târziu, dar asta e pentru mai târziu. Mai jos în text va fi un exemplu.
Să vedem ce avem. Să executăm (pe linia de comandă)

$TimeNow | Get-member

și obțineți o pagină de text de neînțeles

Exemplu de text de neînțeles numărul 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")...                                         

După cum puteți vedea, o variabilă de tip TypeName: System.DateTime a fost creată cu o mulțime de metode (în sensul a ceea ce putem face cu acest obiect variabil) și proprietăți.

Hai sa sunăm $TimeNow.DayOfYear — obținem numărul zilei din an.
Hai sa sunăm $TimeNow.DayOfYear | Get-Member - primim TypeName: System.Int32 și un grup de metode.
Hai sa sunăm $TimeNow.ToUniversalTime() - și obțineți ora în UTC

Depanator

Uneori se întâmplă să fie necesar să executați un program până la o anumită linie și să vedeți starea programului în acel moment. În acest scop, ISE are o funcție Debug - comutare punct de întrerupere
Pune un punct de întrerupere undeva la mijloc, rulează aceste două rânduri și vezi cum arată pauză.

3. Înțelegerea interacțiunii cu botul Telegram

Desigur, s-a scris și mai multă literatură despre interacțiunea cu botul, cu toate getpush și așa mai departe, dar problema teoriei poate fi luată în considerare opțional.

În cazul nostru este necesar:

  • Învață să trimiți ceva prin corespondență
  • Învață să obții ceva din corespondență

3.1 A învăța să trimiți ceva în corespondență și să primești de la el

Un mic cod - partea 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

iar în Federația Rusă în acest moment primim eroarea Nu se poate conecta la serverul de la distanță.

Sau nu îl primim - depinde de operatorul de telecomunicații și dacă proxy-ul este configurat și funcționează
Ei bine, tot ce rămâne este să adăugați un proxy. Vă rugăm să rețineți că utilizarea unui proxy necriptat și în general fraudulos este extrem de periculoasă pentru sănătatea dumneavoastră.

Sarcina de a găsi un proxy funcțional nu este foarte dificilă - majoritatea proxy-urilor http publicate funcționează. Cred că al cincilea a funcționat pentru mine.

Sintaxă folosind proxy:

Invoke-WebRequest -Uri $URL4SEND -Proxy $MyProxy

Dacă primești un mesaj în chat-ul tău cu un bot, atunci totul este în regulă, poți continua. Dacă nu, continuați depanarea.

Puteți vedea în ce se transformă șirul dvs. $URL4SEND și puteți încerca să îl solicitați în browser, astfel:

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

3.2. Am învățat cum să scriem „ceva” în chat, acum să încercăm să-l citim

Să mai adăugăm 4 rânduri și să vedem ce este înăuntru prin | obţine-membru

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

Cel mai interesant lucru ne este oferit

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

Să vedem ce este în ele:

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

Dacă totul funcționează pentru tine, vei primi un rând lung ca:

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

Din fericire, în articolul publicat anterior Telegram bot pentru administratorul de sistem această linie (da, conform $MyMessageGet.RawContent | get-member este System.String), a fost deja dezasamblat.

4. Procesează ceea ce primești (știm deja cum să trimitem ceva)

Așa cum a fost deja scris aici, cele mai necesare lucruri stau în conținut. Să aruncăm o privire mai atentă.

Mai întâi, vom mai scrie câteva fraze botului din interfața web sau de pe telefon

/message1
/message2
/message3

și căutați prin browser adresa care a fost formată în variabila $URLGET.

Vom vedea ceva de genul:

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

Ce este? Unele obiecte complexe din matrice de obiecte care conțin un identificator de mesaj de la capăt la capăt, un identificator de chat, un identificator de trimitere și o mulțime de alte informații.

Cu toate acestea, nu trebuie să ne dăm seama „ce fel de obiect este acesta” - o parte a lucrării a fost deja făcută pentru noi. Să vedem ce este înăuntru:

Citirea mesajelor primite sau partea 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. Ce ar trebui să facem acum?

Să salvăm fișierul rezultat sub numele myfirstbotBT105 sau orice vă place mai mult, schimbați titlul și comentați tot codul deja scris prin

<#start comment 105 end comment 105#>

Acum trebuie să decidem de unde să obținem dicționarul (ei bine, de unde - pe disc într-un fișier) și cum va arăta.

Bineînțeles, puteți scrie un dicționar imens chiar în textul scenariului, dar acest lucru este complet în afara sensului.
Deci, să vedem cu ce poate funcționa Powershell în mod normal.
În general, nu îi pasă cu ce fișier să lucreze, nu contează pentru noi.
Avem de ales: txt (poți, dar de ce), csv, xml.
Putem să-i vedem pe toți?
Să creăm o clasă MyVocabClassExample1 și o variabilă $MyVocabExample1
Observ că clasa este scrisă fără $

ceva cod #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

Să încercăm să scriem asta în fișiere folosind probă.

Unele coduri #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

- și obținem o eroare pe linia Out-File -FilePath $MyFilenameExample01 -InputObject -Append $MyVocabExample2.

Nu vrea să adauge, ah-ah, ce păcat.

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

Să vedem ce se întâmplă. Vedere excelentă a textului - dar cum să-l exportați înapoi? Ar trebui să introduc un fel de separatoare de text, cum ar fi virgulele?

Și în cele din urmă obțineți un „fișier cu valori separate prin virgulă (CSV) A OPRITĂ Așteaptă.
#

$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 

După cum este ușor de văzut, MS nu se distinge în mod deosebit prin logica sa pentru o procedură similară, într-un caz este folosit -FilePath, în altul -Path;

În plus, în al treilea dosar a dispărut limba rusă, în cel de-al patrulea dosar s-a dovedit... ei bine, ceva s-a întâmplat. #TYPE System.Object[] 00
# „Număr”, „Lungime”, „Lungime lungă”, „Rank”, „SyncRoot”, „IsReadOnly”, „IsFixedSize”, „Este sincronizat”
#
Să o rescriem puțin:

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

Se pare că a ajutat, dar încă nu îmi place formatul.

În special, nu îmi place că nu pot pune linii dintr-un obiect într-un fișier direct.
Apropo, de când am început să scriem în fișiere, putem începe să păstrăm un jurnal de pornire? Avem timp ca variabilă, putem seta numele fișierului.

Adevărat, încă nu există nimic de scris, dar vă puteți gândi la cel mai bun mod de a roti bustenii.
Să încercăm xml pentru moment.

Niște 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

Exportul în xml are multe avantaje - lizibilitate, exportul întregului obiect și nu este nevoie să efectuați o schimbare.

Să încercăm citește fișierul xml.

O mică lectură din xml

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

Să revenim la sarcină. Am scris un fișier de test, l-am citit, formatul de stocare este clar, dacă este necesar, puteți scrie un editor mic de fișiere separat pentru a adăuga și a șterge linii.

Permiteți-mi să vă reamintesc că sarcina a fost să faceți un bot mic de antrenament.

Format de lucru: trimit comanda „exemplu” către bot, botul îmi trimite un cuvânt și transcriere alese aleatoriu, iar după 10 secunde îmi trimite o traducere și un comentariu. Știm să citim comenzile, am dori, de asemenea, să învățăm cum să selectăm și să verificăm automat proxy-urile și să resetam contoarele de mesaje la uitare.

Să decomentăm tot ce a comentat anterior ca fiind inutil, să comentăm exemplele acum inutile cu txt și csv și să salvăm fișierul ca versiunea B106

O da. Să trimitem ceva botului din nou.

6. Expediere de la funcții și multe altele

Înainte de a procesa recepția, trebuie să creați o funcție pentru a trimite „cel puțin ceva” în afară de un mesaj de testare.

Desigur, în exemplu vom avea o singură trimitere și o singură procesare, dar dacă trebuie să facem același lucru de mai multe ori?

Este mai ușor să scrieți o funcție. Deci, avem o variabilă de tip obiect $MyVocabExample4AsArray, citită din fișier, sub forma unui tablou de cât mai multe elemente.
Hai să citim.

În același timp, ne vom ocupa de ceasul, vom avea nevoie de el mai târziu (de fapt, în acest exemplu nu vom avea nevoie de el;)

Unele coduri #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
}

După cum puteți vedea cu ușurință, funcția apelează $MyToken și $MyChatID, care au fost codificate mai devreme.

Nu este nevoie să faceți acest lucru, iar dacă $MyToken este unul pentru fiecare bot, atunci $MyChatID se va schimba în funcție de chat.

Cu toate acestea, deoarece acesta este un exemplu, îl vom ignora pentru moment.

Deoarece $MyVocabExample4AsArray nu este un tablou, deși este foarte asemănător cu unul, atunci nu poți să o iei pur și simplu cere lungimea acestuia.

Încă o dată va trebui să facem ceva ce nu se poate face - parașuta nu conform codului - luați-o și numărați

Unele coduri #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)
# Угадайте сами, какой пример легче читается посторонними людьми.

Întâmplător caracteristică interesantă. Să presupunem că vrem să primim 0 sau 1 (avem doar două elemente în matrice). Când stabilim limitele 0..1, vom obține „1”?
nu - nu o vom obține, avem un exemplu special Exemplul 2: Obțineți un număr întreg aleatoriu între 0 și 99 Get-Random -Maximum 100
Prin urmare, pentru 0..1 trebuie să setăm dimensiunea 0..2, cu numărul maxim de element = 1.

7. Procesarea mesajelor primite și lungimea maximă a cozii

Unde ne-am oprit mai devreme? avem variabila primită $MyMessageGet
și $Content4Pars01 obținut din acesta, dintre care ne interesează elementele matricei Content4Pars01.result

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

Să trimitem botul /message10, /message11, /message12, /word și din nou /word și /hello.
Să vedem ce avem:

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

Să parcurgem tot ce am primit și să trimitem un răspuns dacă mesajul a fost /word
cazul constructului, ceea ce unii descriu ca if-elseif, este numit în powershell prin comutator. În același timp, codul de mai jos folosește cheia -wildcard, care este complet inutilă și chiar dăunătoare.

Unele coduri #7.1

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

Să rulăm scriptul de câteva ori. Vom primi același cuvânt de două ori pentru fiecare încercare de execuție, mai ales dacă am făcut o greșeală în implementarea random.

Dar oprește-te. Nu am trimis /word din nou, așa că de ce mesajul este procesat din nou?

Coada pentru trimiterea mesajelor către bot are o lungime finită (100 sau 200 de mesaje, cred) și trebuie șters manual.

Desigur, acest lucru este descris în documentație, dar trebuie să îl citiți!

În acest caz, avem nevoie de parametrul ?chat_id, iar &timeout, &limit, &parse_mode=HTML și &disable_web_page_preview=true nu sunt încă necesare.

Documentatie pentru Telegram API este aici
Scrie în alb și engleză:
Identificatorul primei actualizări care va fi returnată. Trebuie să fie mai mare cu unu decât cea mai mare dintre identificatorii actualizărilor primite anterior. În mod implicit, actualizările încep cu cele mai vechi
neconfirmat actualizare sunt returnate. O actualizare este considerată confirmată de îndată ce getUpdates este apelat cu un compensa superior decât update_id-ul său. Offset-ul negativ poate fi specificat pentru a prelua actualizări începând de la -offset update de la sfârșitul cozii de actualizări. Toate actualizările anterioare vor fi uitate.

Să ne uităm la:

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

Da, și îl vom reseta și vom rescrie puțin funcția. Avem două opțiuni - transmiteți întregul mesaj funcției și procesați-l în întregime în funcție, sau dați doar ID-ul mesajului și resetați-l. De exemplu, al doilea pare mai simplu.

Anterior, șirul nostru de interogări „toate mesajele” arăta

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

si va arata ca

$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 

Nimeni nu vă interzice să primiți mai întâi toate mesajele, să le procesați și numai după procesarea cu succes cererea neconfirmată -> confirmată.

De ce are sens să confirmați apelul după ce s-a încheiat toată procesarea? Un eșec este posibil în mijlocul execuției, iar dacă, de exemplu, un chatbot gratuit, pierderea unui singur mesaj nu este nimic special, atunci dacă procesați salariul cuiva sau tranzacția cu cardul, rezultatul poate fi mai rău.

Încă câteva rânduri de cod

$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. În loc de o concluzie

Funcțiile de bază - citirea mesajelor, resetarea cozii, citirea din fișier și scrierea în fișier sunt realizate și afișate.

Mai sunt doar patru lucruri de făcut:

  • trimiterea răspunsului corect la o solicitare în chat
  • trimiterea unui răspuns la ORICE chat la care a fost adăugat botul
  • executarea codului într-o buclă
  • lansarea unui bot din planificatorul Windows.

Toate aceste sarcini sunt simple și pot fi realizate cu ușurință citind documentația despre parametri precum
Set-ExecutionPolicy Unrestricted și -ExecutionPolicy Bypass
ciclul formei

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

Mulțumesc tuturor celor care au citit.

Sursa: www.habr.com

Adauga un comentariu