Cu ocazia discuțiilor cu un prieten, am aflat brusc că elevii din clasele a 8-a și a 10-a de la școala lor nu învață deloc programare. Word, Excel și atât. Nicio logică, nici măcar Pascal, nici VBA pentru Excel.
Am fost foarte surprins, am deschis internetul și am început să citesc —
Una dintre sarcinile școlii de profil este să contribuie la formarea unei noi generații, care să corespundă în nivelul său de dezvoltare și stilul de viață condițiilor societății informaționale.
Acest curs va permite consolidarea în practică a cunoștințelor elevilor despre structurile de bază ale limbajului de programare Pascal. (din programul unei anumite gimnazii din 2017)
În cele din urmă, am decis să îmi dedic câteva ore și să schițez un exemplu despre "cum să creezi un bot simplu - pentru elevi".
Sub titlu, despre cum să scrii un alt bot simplu pe PowerShell și să-l faci să funcționeze fără webhook, IP-uri publice, servere dedicate, mașini virtuale în cloud și tot așa — pe un PC obișnuit de acasă cu Windows obișnuit.
TLDR: Un alt articol plictisitor cu erori gramaticale și factuale, nu e nimic de citit, nu are umor și nu are imagini.
Nu este nimic nou în articol, aproape tot ce este scris aici a fost deja pe Habr, de exemplu în articolele și .
Mai mult decât atât, articolul este deliberat redundant, pentru a nu face referire la fiecare pas la literatură didactică. Nicio referință la banda 4, PowerShell Deep Dives sau, să zicem, The 5 Pillars of the AWS Well-Architected Framework nu se găsește în text.
În loc de prefață, o putem sări
Săriți fără ezitareÎn 2006, Microsoft a lansat PowerShell 1.0 pentru Windows XP, Vista și serverul 2003. Într-un fel, a înlocuit lucruri precum scripturile cmdbat, scripturile vb, Windows Script Host și JScript.
Chiar și acum, PowerShell poate fi considerat doar ca un pas următor după variantele Logo, în loc de Delphi (sau ceva și mai vechi), în ciuda existenței causelor, claselor, funcțiilor, apelului MS GUI, și așa mai departe.
PowerShell este utilizat relativ rar, întâlnindu-se doar sub forma PowerShell Core, VMware vSphere PowerCLI, Azure PowerShell, MS Exchange, Desired State Configuration, și încă câteva zeci de programe și funcții folosite rar. Poate, va avea o a doua șansă odată cu apariția , dar nu este sigur.
PowerShell are și trei mari avantaje:
- Este relativ simplu, există o mulțime de literatură și exemple despre el, chiar și în rusă, de exemplu, un articol despre Foreach — dintr-o carte — despre diferența dintre () și {}
- Vine împreună cu editorul , inclus în Windows. Există chiar și un debugger.
- Din el se pot apela cu ușurință .
0. Pregătire.
Ne va fi necesar:
- Un PC cu Windows (eu am Windows 10)
- Oricum, o conexiune la internet (de exemplu, prin NAT)
- Pentru cei care au acces limitat la Telegram — un freegate instalat și configurat în browser, în unele cazuri complexe, împreună cu Symple DNS Crypt
- Un client Telegram funcțional pe telefon
- Înțelegerea unor noțiuni de bază — ce este o variabilă, un array, un ciclu.
Articolele deschise și citite — și
1. Vom crea un nou bot de test.
Deoarece toată lumea știe deja asta și a fost mai înainte, se poate sări și peste astaCum este menționat în articolul de mai sus — În primul rând, un bot pentru Telegram — este în continuare o aplicație care rulează de partea dumneavoastră și face cereri la Telegram Bot API. API-ul este clar — botul apelează o anumită URL cu parametrii, iar Telegram răspunde cu un obiect JSON.
Problemele asociate: dacă în vreun fel misterios luați un cod din obiectul JSON și trimiteți-l spre execuție (nu intenționat) — codul se va executa.
Procesul de creație este descris în cele două articole de mai sus, dar voi repeta: în Telegram deschidem contacte, căutăm @botfather, îi spunem /newbot, vom crea un bot Botfortest12344321, îl vom numi Mynext1234bot și vom primi un mesaj cu o cheie unică de tipul 1234544311:AbcDefNNNNNNNNNNNNN
Salvați cheia și nu o distribuiți!
Apoi putem configura botul, de exemplu, să interzicem adăugarea lui în grupuri, dar în primele etape nu este necesar.
Îl întrebăm pe BotFather „/mybot” și corectăm setările, dacă nu ne place ceva.
Din nou, vom deschide contacte, îl vom găsi pe @Botfortest12344321 (începeți căutarea cu @), vom apăsa „începe” și vom scrie botului „/Slava robotam”. Semnul / este obligatoriu, ghilimelele nu sunt necesare.
Botul, desigur, nu va răspunde.
Să verificăm dacă botul a fost creat — îl vom deschide.
:AbcDefNNNNNNNNNNNNN/getMe
unde 1234544311:AbcDefNNNNNNNNNNNNN — cheia obținută anterior,
și vom obține un șir de tipul
{„ok”:true,„result”:{„”}}
Primul cod secret (token) este deja la noi. Acum trebuie să aflăm al doilea cod secret — ID-ul chat-ului cu botul. Fiecare chat, grup etc. sunt unice și au propriul număr (uneori cu minus — pentru grupurile deschise). Pentru a obține acest număr, trebuie să cerem în browser (deși nu este absolut necesar să fie în browser, dar pentru o mai bună înțelegere, putem începe de acolo) adresa (unde 1234544311:NNNNNNNNN — este token-ul tău
https://api.telegram.org/bot1234544311:NNNNNNNNN/getUpdates
și să primim un răspuns de tipul
{«ok»:true,«result»:[{«update_id»:…,… chat«:{«id»:123456789
Avem nevoie exact de chat_id.
Să verificăm că putem scrie în chat manual: vom apela din browser adresa
https://api.telegram.org/botvahtoken/sendMessage?chat_id=123456789&text="Life is directed motion"Dacă ai primit un mesaj în chat de la bot — ok, poți trece la următorul pas.
Astfel (prin browser) poți verifica întotdeauna unde sunt problemele — dacă este la generarea link-ului, sau dacă ceva este ascuns și nu funcționează.
Ce trebuie să știi înainte de a continua lectura
În Telegram există mai multe tipuri de chat-uri de grup (deschise, închise). Pentru aceste chat-uri, unele funcții (de exemplu, id) diferă, ceea ce uneori generează probleme.
Să presupunem că suntem la sfârșitul anului 2019, iar chiar și eroul vremurilor noastre, bine cunoscutul Om-Orchestră (administrator, jurist, specialist în securitate informațională, programator și practic MVP) Evgheni V. deosebește variabila $i de un array, a stăpânit buclele și, cine știe, în următorii câțiva ani va învăța Chocolatey, iar apoi va ajunge la și va ajunge.
1. Ne gândim, ce va face botul nostru
Nu aveam nicio idee, așa că a trebuit să mă gândesc. Am mai scris un bot-notiță. Nu voiam să fac un bot care "trimite ceva undeva". Pentru conectarea la Azure este nevoie de un card de credit, iar de unde să aibă un elev? Trebuie să menționez că lucrurile nu sunt atât de rele: majoritatea cloud-urilor oferă o perioadă de testare gratuită (dar tot ai nevoie de un număr de card de credit — și de pe el va fi retras, cred, un dolar. Nu-mi amintesc dacă s-a întors ulterior.)
Fără AI ML, a face un bot-care-colecționează-versuri nu este atât de interesant.
Am decis să fac un bot care să îmi aducă aminte de cuvintele din engleză din dicționar.
Dicționarul, pentru a nu avea de-a face cu baza de date, va fi stocat într-un fișier text și va fi completat manual.
În acest caz, scopul este de a arăta bazele funcționării, nu de a crea un produs complet gata.
2. Încercăm ce și cum pentru prima dată
Vom crea un folder C:poshtranslate
Pentru început, să vedem ce avem de-a face cu powershell, vom lansa ISE prin executare rapidă
powershell ise
sau găsim Powershell ISE în programele instalate.
După lansare, se va deschide un editor obișnuit, iar dacă nu există câmp de text, întotdeauna putem apăsa „File — create new”.
Să verificăm versiunea powershell — vom scrie în câmpul de text:
get-host
și vom apăsa F5.
Powershell va propune să salvăm — „The script you are about to run will be saved.”, să acceptăm și să salvăm în C:poshtranslate fișierul din powershell cu numele myfirstbotBT100.
După execuție, în fereastra de text din partea de jos vom obține un tabel de date:
Nume : Windows PowerShell ISE Host
Versiune : 5.1.(și așa mai departe)
Am 5.1 cu ceva, este suficient. Dacă ai un Windows 7/8 mai vechi, nu este nicio problemă — deși PowerShell trebuie actualizat la versiunea 5 — de exemplu, prin .
Vom scrie în linia de comandă de jos Get-Date, apăsăm Enter, ne uităm la timp, vom merge în folderul rădăcină cu comanda
cd
și vom curăța ecranul cu comanda cls (nu, nu trebuie să folosești rm)
Acum să verificăm ce și cum funcționează — vom scrie nu cod, ci două linii și vom încerca să înțelegem ce fac. Vom comenta linia cu get-host cu simbolul # și vom adăuga puțin.
# Пример шаблона бота
# get-host
<# это пример многострочного комментария #>
$TimeNow = Get-Date
$TimeNow
(Ce este interesant. În lista derulantă de formatare a codului de pe habra, există douăzeci de opțiuni — dar powershell nu este acolo. Dos este. Perl este.)
Și vom rula codul, apăsând F5 sau „>” din GUI.
Vom obține o ieșire:
Sâmbătă, 8 decembrie 2019 21:00:50 PM (sau ceva de genul acesta)
Acum să ne ocupăm de aceste două linii și de câteva momente interesante, pentru a nu ne mai întoarce la asta mai târziu.
Spre deosebire de Pascal (și nu numai), PowerShell încearcă singur să determine ce tip să aloce variabilei, despre care este discutat mai în detaliu în articolul
Așadar, atunci când creăm variabila $TimeNow și îi atribuim valoarea datei și orei curente (Get-Date), nu trebuie să ne facem griji în mod special ce tip de date va fi acolo.
Desigur, ignoranța aceasta poate provoca dureri mai târziu, dar asta va fi mai târziu. În textul de mai jos va fi un exemplu.
Să vedem ce am obținut. Vom executa (în linia de comandă)
$TimeNow | Get-memberși vom obține o pagină de text ciudat
Exemplul de text ciudat nr. 1
PS C:> $TimeNow | Get-member
TypeName: System.DateTime
Name MemberType Definition
---- ---------- ----------
Adăuga <b>Metodă </b>datetime Adăugare(timespan value)
..
DisplayHint NoteProperty DisplayHintType DisplayHint=DateTime
Data <b>Proprietate </b>datetime Data {get;}
An Proprietate int An {get;}
..
DateTime ScriptProperty System.Object DateTime {get=if ((& { Set-StrictMode -Version 1; $this.DisplayHint }) -ieq "Data")...
După cum se poate observa, a fost creată o variabilă de tip TypeName: System.DateTime cu multe metode (în sensul că putem face cu această variabilă obiect) și proprietăți.
Vom apela $TimeNow.DayOfYear — vom obține numărul zilei în an.
Vom apela $TimeNow.DayOfYear | Get-Member — vom obține TypeName: System.Int32 și grupul de metode.
Vom apela $TimeNow.ToUniversalTime() — și vom obține ora în UTC
Debugger
Uneori este necesar să executați un program până la o anumită linie și să verificați starea programului în acel moment. Pentru aceasta, în ISE există funcția Debug — toggle break point.
Plasați un punct de oprire undeva pe la mijloc, rulați aceste două linii pentru execuție și verificați cum arată oprirea.
3. Să discutăm despre interacțiunea cu botul Telegram
Desigur, despre interacțiunea cu botul, toate getpush și așa mai departe, s-a scris și mai multă literatură, totuși, întrebarea teoretică poate fi discutată opțional.
În cazul nostru, este necesar:
- Să învățăm să trimitem ceva în conversație
- Să învățăm să primim ceva din conversație
3.1 Învățăm să trimitem ceva în conversație și să primim din ea
Puțin cod — partea 3
Write-output "Aceasta este partea 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 = "Viața este mișcare direcționată - " + $TimeNow
$URL4SEND = "https://api.telegram.org/bot$MyToken/sendMessage?chat_id=$MyChatID&text=$MyText01"
Invoke-WebRequest -Uri $URL4SEND
și în RF în acest loc primim o eroare Unable to connect to the remote server.
Sau nu primim — depinde de operatorul de telefonie și de modul în care este configurat și funcționează proxy-ul
Ei bine — rămâne să adăugăm proxy. Țineți cont — utilizarea unui proxy necriptat și în general străin este extrem de periculoasă pentru sănătatea voastră.
Sarcina de a găsi un proxy funcțional nu este foarte complicată — cea mai mare parte a proxy-urilor http publicate funcționează. Cred că mi-a funcționat a cincea de pe listă.
Sintaxa de utilizare a proxy-ului:
Invoke-WebRequest -Uri $URL4SEND -Proxy $MyProxy
Dacă ați primit un mesaj în chat-ul vostru cu botul — este excelent, puteți continua. Dacă nu, continuați depanarea.
Puteți verifica în ce se transformă șirul vostru $URL4SEND și să încercați să-l solicitați în browser, de exemplu așa:
$URL4SEND2 = '"'+$URL4SEND+'"'
start chrome $URL4SEND2
3.2 Am învățat să scriem „ceva” în chat, acum vom încerca să citim
Vom adăuga încă 4 linii și vom verifica ce se află în interior prin | get-member
$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 ne este oferit de
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 # aici este ceva interesant
Write-Host "RawContent"
$MyMessageGet.RawContent # și aici este ceva interesant, dar de asemenea și lizibil.
Write-Host "Content"
$MyMessageGet.Content
Dacă totul funcționează, veți obține un șir lung de tipul:
{"ok":true,"result":[{"update_id":12345678,
"message":{"message_id":3,"from":{"id"Din păcate, în articolul anterior despre botul Telegram pentru administratorii de sistem, această linie (da, conform $MyMessageGet.RawContent | get-member — este System.String), a fost deja analizată.
4. Procesați ceea ce a fost primit (deja știm să trimitem ceva)
Așa cum s-a menționat deja , cel mai necesar se află în content. Să ne uităm mai atent.
Mai întâi, să scriem botului încă câteva fraze din interfața web sau de pe telefon
/message1
/message2
/message3și să vizualizăm prin browser adresa generată î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 acest lucru? Un obiect complex din array-uri de obiecte, conținând un identificator unic al mesajului, identificatorul chat-ului, identificatorul expedierii și multe alte informații.
Cu toate acestea, nu avem nevoie să deslușim „ce este acest obiect” — o parte din muncă a fost deja făcută pentru noi. Să vedem ce există în interior:
Citirea mesajelor primite sau partea 4
Write-Host "Aceasta este partea 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 trebuie să facem acum cu asta?
Vom salva fișierul primit sub numele myfirstbotBT105 sau oricum vă place mai mult, vom schimba titlul și vom comenta tot codul deja scris prin
<#start comment 105 end comment 105#>
Acum trebuie să ne hotărâm unde să luăm dicționarul (păi unde — pe disc într-un fișier) și cum va arăta acesta.
Desigur, putem să umplem un dicționar uriaș chiar în textul scriptului, dar acesta nu este deloc un mod bun.
Așadar, să vedem cu ce lucrează PowerShell în mod nativ.
De fapt, lui nu-i pasă cu ce fișier lucrează, dar nouă ne pasă.
Avem de ales: txt (se poate, dar de ce), csv, xml.
Sau putem vizualiza pe toți. Să îi privim pe toți.
Vom crea clasa MyVocabClassExample1 și variabila $MyVocabExample1
observ că clasa se scrie fără $
puțin cod #5
write-host "Aceasta este partea 5"
class MyVocabClassExample1 {
[string]$Original # cuvânt
[string]$Transcript
[string]$Translate
[string]$Example
[int]$VocWordID # un moment foarte interesant. Utilizarea int cu limitările sale poate duce uneori la consecințe neașteptate, de exemplu - cazul recent cu SSD HPE. Inițial nu am adăugat acest element, dar apoi l-am completat și comentat.
}
$MyVocabExample1 = [MyVocabClassExample1]::new()
$MyVocabExample1.Original = "Apple"
$MyVocabExample1.Transcript = "[ ˈapəl ]"
$MyVocabExample1.Translate = "Măr"
$MyVocabExample1.Example = "Un măr este un fruct dulce și comestibil produs de un măr (Malus domestica)"
# $MyVocabExample1.$VocWordID = 1
$MyVocabExample2 = [MyVocabClassExample1]::new()
$MyVocabExample2.Original = "Pear"
$MyVocabExample2.Transcript = "[ pe(ə)r ]"
$MyVocabExample2.Translate = "Pară"
$MyVocabExample2.Example = "Pariul (ˈpɛər) este un specii din genul Pyrus"
# $MyVocabExample1.$VocWordID = 2
Să încercăm să înregistrăm asta în fișiere după .
Puțin cod #5.1
Write-Host $ScriptDir # sper că nu ați comentat $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 vom primi o eroare pe linia Out-File -FilePath $MyFilenameExample01 -InputObject -Append $MyVocabExample2.
Nu vrea să adauge, of of ce supărare.
$MyVocabExample3AsArray = @($MyVocabExample1,$MyVocabExample2)
Out-File -FilePath $MyFilenameExample02 -InputObject $MyVocabExample3AsArray
notepad $MyFilenameExample02
Să vedem ce a ieșit. O formă text frumoasă — dar cum se exportă înapoi din ea? Să introduc ceva delimitatori de text, cum ar fi virgulele?
Și în final să obținem „fișier cu delimitatori — virgule, valori separate prin virgulă (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
Este ușor de observat, MS nu s-a diferențiat prea mult în logică, pentru o procedură similară într-un caz se folosește -FilePath, într-un altul -Path.
În plus, în al treilea fișier a dispărut limba rusă, în al patrulea fișier a ieșit… ei bine, a ieșit ceva. #TYPE System.Object[] 00
# „Count“,»Length»,«LongLength»,«Rank»,«SyncRoot»,«IsReadOnly»,«IsFixedSize»,«IsSynchronized»
#
Să 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 formatul tot nu-mi place.
În special, nu-mi place că nu pot să introduc liniile din obiect direct într-un fișier.
Apropo, acum că am început să scriem în fișiere — poate am putea începe să ținem un jurnal de execuție? Avem timpul ca variabilă și știm să specificăm numele fișierului.
De scris, de fapt, nu avem încă nimic, dar putem să ne gândim cum să facem mai bine rotația jurnalelor.
Pentru început, să încercăm xml.
Puțin 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
Exportarea în xml are doar avantaje — lizibilitate, exportarea întregului obiect și nu trebuie să facem uppend.
Să încercăm .
Puțină citire din xml
$MyFilenameExample06 = $ScriptDir + "Example06.xml"
$MyVocabExample4AsArray = Import-Clixml -Path $MyFilenameExample06
# $MyVocabExample4AsArray
# $MyVocabExample4AsArray[0]
# și ceva despre nuanțele complet neclare. Powershell se comportă din când în când diferit de cum s-ar aștepta de obicei.
# de exemplu, aceste două ieșiri diferă
# Write-Output $MyVocabExample4AsArray
# write-host $MyVocabExample4AsArray
Să ne întoarcem la sarcină. Fișierul de test l-am scris, l-am citit, formatul de stocare este clar, iar dacă este nevoie, putem scrie un editor mic pentru a adăuga și șterge linii.
Aduc aminte că sarcina a fost să creăm un mic bot de învățare.
Formatul de lucru: eu trimit botului comanda „exemplu”, botul îmi trimite un cuvânt ales aleatoriu și transcrierea, iar după 10 secunde trimite traducerea și comentariul. Știm să citim comenzile, ar mai trebui să învățăm să selectăm și să verificăm automat proxy-urile și să resetăm contoarele de mesaje în uitare.
Să decomentăm tot ce am comentat anterior ca fiind inutil, să comentăm exemplele care au devenit inutile cu txt și csv și să salvăm fișierul ca versiunea B106
Ah, da. Să trimitem ceva botului din nou.
6. Trimiterea din funcții și nu numai
Înainte de a procesa primirea, trebuie să facem o funcție de trimitere „orice”, în afară de mesajul de test.
Desigur, în exemplul nostru va fi doar o singură trimitere și tot dintr-o singură procesare, dar dacă va fi nevoie să facem același lucru de mai multe ori?
Mai simplu este să scriem o funcție. Așadar, avem o variabilă de tip obiect $MyVocabExample4AsArray, citită din fișier, sub formă de array cu două elemente.
În același timp, să ne ocupăm de ceasuri, ne va trebui mai târziu (de fapt, în acest exemplu — nu va fi nevoie 🙂
Puțin cod #6.1
Write-Output "Acesta este Partea 6"
$Timezone = (Get-TimeZone)
IF($Timezone.SupportsDaylightSavingTime -eq $True){
$TimeAdjust = ($Timezone.BaseUtcOffset.TotalSeconds + 3600) } # ora corespunzătoare
ELSE{$TimeAdjust = ($Timezone.BaseUtcOffset.TotalSeconds)
}
function MyFirstFunction($SomeExampleForFunction1){
$TimeNow = Get-Date
$TimeNow.ToUniversalTime()
# $MyText02 = $TimeNow + " " + $SomeExampleForFunction1 # și aici vom avea o eroare
$MyText02 = $SomeExampleForFunction1 + " " + $TimeNow # iar aici nu vom avea, cine își dă seama de ce - acela e deștept.
$URL4SendFromFunction = "https://api.telegram.org/bot$MyToken/sendMessage?chat_id=$MyChatID&text=$MyText02"
Invoke-WebRequest -Uri $URL4SendFromFunction -Proxy $MyProxy
}
Se vede ușor că în funcție sunt apelate $MyToken și $MyChatID, care au fost setate anterior.
Acest lucru nu ar trebui făcut, și, 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, deocamdată vom ignora acest lucru.
Deoarece $MyVocabExample4AsArray nu este un array, deși arată foarte mult ca unul, nu poți pur și simplu să îi soliciți lungimea.
Va trebui din nou să facem ceea ce nu ar trebui - să ne aventurăm în afara codului - să luăm și să numărăm
Puțin cod #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)
# sau într-o singură linie
# MyFirstFunction($MyVocabExample4AsArray[Get-Random -Minimum 0 -Maximum ($MaxRandomExample -1)].Example)
# Ghiciți singuri, care exemplu este mai ușor de citit de către persoanele externe.
Aleator . Să presupunem că dorim să obținem 0 sau 1 (avem doar două elemente în array). La setarea limitelor 0..1 — vom obține „1”?
nu — nu vom obține, avem un exemplu definit special Example 2: Obține un integer aleator între 0 și 99 Get-Random -Maximum 100
Așadar, pentru 0..1 va trebui să setăm dimensiunea 0..2, având în vedere că numărul maxim al elementului = 1.
7. Procesarea mesajelor primite și lungimea maximă a cozii
Pe ce am rămas anterior? avem variabila obținută $MyMessageGet
și $Content4Pars01 obținut din aceasta, din care ne interesează elementele array-ului Content4Pars01.result
$Content4Pars01.result[0].update_id
$Content4Pars01.result[0].message
$Content4Pars01.result[0].message.text Vom trimite botului /message10, /message11, /message12, /word și încă o dată /word și /salut.
Să vedem ce am obținut:
$Content4Pars01.result[0].message.text
$Content4Pars01.result[2].message.text Vom parcurge tot ceea ce am primit și vom trimite un răspuns, dacă mesajul a fost /word
structura case of, ceea ce unii descriu ca if-elseif, în powershell este apelată . În codul de mai jos, s-a folosit cheia -wildcard, ceea ce nu este deloc necesar și poate fi chiar dăunător.
Puțin cod #7.1
Write-Output "Aceasta este partea 7"
Foreach ($Result in $Content4Pars01.result) # Da, se poate face mai repede
{
switch -wildcard ($Result.message.text)
{
"\/word" {MyFirstFunction($TextForExample1)}
}
}
Vom rula scriptul de câteva ori. Vom obține același cuvânt de două ori la fiecare tentativă de execuție, mai ales dacă am greșit implementarea random.
Dar stop. Noi nu am trimis încă \/word, de ce se procesează mesajul din nou?
Coada pentru trimiterea mesajelor către bot are o lungime limitată (pare a fi 100 sau 200 de mesaje) și trebuie curățată manual.
În documentație este, desigur, descris, dar trebuie să o citim!
În acest caz, avem nevoie de parametrul ?chat_id, iar &timeout, &limit, &parse_mode=HTML și &disable_web_page_preview=true nu sunt necesare încă.
Documentația despre În engleză, este scris alb pe negru:
Identifier of the first update to be returned. Must be greater by one than the highest among the identifiers of previously received updates. By default, updates starting with the earliest
unconfirmed update are returned. An update is considered confirmed as soon as getUpdates is called with an offset higher than its update_id. Offset-ul negativ poate fi specificat pentru a recupera actualizări începând de la -offset actualizare 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Și să resetăm — să rescriem puțin funcția. Avem două opțiuni — să transmitem în funcție toate mesajele și să le procesăm integral în funcție, sau să returnăm doar ID-ul mesajului și să-l resetăm pe acesta. Ca exemplu, a doua opțiune pare mai simplă.
Anterior, șirul de interogare pentru "toate mesajele" arăta așa
$URLGET = "https:\/\/api.telegram.org\/bot$MyToken\/getUpdates"iar acum va arăta așa
$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 interzice să obținem mai întâi toate mesajele, să le procesăm și doar după ce am procesat cu succes să solicităm unconfirmed -> confirmed.
De ce are sens să apelăm confirmarea după finalizarea tuturor procesărilor? Poate apărea o eroare în mijlocul execuției și, dacă pentru un chatbot gratuit trecerea unui mesaj singular nu este deosebit de importantă, când procesezi salariul cuiva sau o tranzacție cu cardul, rezultatul poate fi mai rău.
Încă câteva linii de cod
$LastMessageId = ($Content4Pars01.result | select -last 1).update_id #eroarea de aici se presupune că trebuie corectată de către utilizator.
$URLGET1 = "https://api.telegram.org/bot$mytoken/getUpdates?offset=$LastMessageId&limit=100"
Invoke-WebRequest -Uri $URLGET1 -Method Get -Proxy $MyProxy
8. În loc de concluzie
Funcțiile principale — citirea mesajelor, resetarea cozii, citirea din fișier și scrierea în fișier sunt realizate și prezentate.
Au rămas de făcut doar patru lucruri:
- trimiterea unui răspuns corect la solicitare în chat
- trimiterea unui răspuns în ORICE chat în care a fost adăugat botul
- executarea codului într-un ciclu
- pornirea botului din planificatorul Windows.
Toate aceste sarcini sunt simple și ușor de implementat cu ajutorul documentației pentru astfel de parametri, cum ar fi
Set-ExecutionPolicy Unrestricted și -ExecutionPolicy Bypass
un ciclu de tipul
$TimeToSleep = 3 # interogare la fiecare 3 secunde
$TimeToWork = 10 # minute
$HowManyTimes = $TimeToWork*60/$TimeToSleep # contor pentru ciclu
$MainCounter = 0
for ($MainCounter=0; $MainCounter -le $HowManyTimes) {
sleep $TimeToSleep
$MainCounter ++
Mulțumesc tuturor celor care au citit până la capăt.
Sursa: habr.com
