Modello di un semplice bot per Telegram per studenti delle classi 7-9 in Powershell

Durante una conversazione con un amico, ho scoperto con sorpresa che nella loro scuola gli studenti delle classi 8-10 non ricevono affatto insegnamenti di programmazione. Solo Word, Excel e basta. Niente Logo, niente Pascal, niente VBA per Excel.

Sono rimasto molto sorpreso, ho aperto internet e ho iniziato a leggere —
Uno degli obiettivi delle scuole specializzate è favorire la formazione di una nuova generazione, che corrisponda al proprio livello di sviluppo e allo stile di vita delle condizioni della società dell'informazione.
Questo corso permetterà di consolidare nella pratica le conoscenze degli studenti sulle principali strutture del linguaggio di programmazione Pascal. (dalla programmazione di qualche ginnasio del 2017)

Alla fine ho deciso di dedicare un paio d'ore e abbozzare un esempio "di come creare un semplice bot — per gli studenti".

Sotto, si parla di come scrivere un altro semplice bot in Powershell e farlo funzionare senza webhook, IP bianchi, server dedicati, virtual machine nel cloud e altre cose — su un normale PC domestico con Windows normale.

TLDR: Un altro articolo noioso con errori grammaticali e di fatto, non c'è nulla da leggere, nessun umorismo, nessuna immagine.

Non c'è nulla di nuovo nell'articolo, quasi tutto ciò che è scritto era già presente su Habra, ad esempio negli articoli Istruzione: Come creare bot in Telegram e Bot di Telegram per amministratori di sistema.
Inoltre, l'articolo è volutamente ridondante, per non dover fare riferimento ogni volta alla letteratura didattica. Non ci sono citazioni su banda 4, PowerShell Deep Dives o, per dire, The 5 Pillars of the AWS Well-Architected Framework nel testo.

Invece di un'introduzione, possiamo saltarla

Facciamo saltare senza problemiNel 2006 Microsoft ha rilasciato PowerShell 1.0 per Windows XP, Vista e server 2003 all'epoca. In qualche modo ha sostituito cose come gli script cmdbat, gli script vb, Windows Script Host e JScript.

Anche oggi PowerShell può essere considerato solo come il passo successivo dopo le varianti di Logo, piuttosto che dove probabilmente si usano ancora Delphi (o qualcosa di più datato), nonostante la presenza di cicli, classi, funzioni, chiamate MS GUI, integrazione con Git e così via.

PowerShell è usato relativamente raramente, si può incontrarlo solo sotto forma di PowerShell Core, VMware vSphere PowerCLI, Azure PowerShell, MS Exchange, Desired State Configuration, PowerShell Web Access e un'altra dozzina di programmi e funzioni raramente utilizzati. Forse, avrà nuova vita con il rilascio di WSL2, ma non è certo.

PowerShell ha anche tre grandi vantaggi:

  1. È relativamente semplice, ci sono molti libri e esempi su di esso, anche in russo, ad esempio un articolo su Foreach – dal libro PowerShell in depth – sulla differenza () e {}
  2. Viene fornito insieme all'editor ISE, incluso in Windows. C'è anche un debugger incluso.
  3. Da esso è facile invocare i componenti per costruire un'interfaccia grafica.

0. Preparazione.

Avremo bisogno di:

  • Un PC con Windows (io ho Windows 10)
  • Qualche tipo di accesso a Internet (ad esempio attraverso NAT)
  • Per coloro che hanno accesso limitato a Telegram – freegate installato e configurato nel browser, in alcuni casi complessi insieme a Symple DNS Crypt
  • Avere un client Telegram funzionante sul telefono
  • Comprendere le basi – cos'è una variabile, un array, un ciclo.

Articoli aperti e letti – Istruzione: Come creare bot in Telegram e Bot di Telegram per amministratori di sistema

1. Creiamo un altro bot di prova.

Dato che tutto ciò è già noto e è già stato fatto, può essere saltatoCome detto nell'articolo sopra – Prima di tutto, un bot per Telegram – è ancora un'applicazione eseguita dalla tua parte e che invia richieste all'API di Telegram Bot. Inoltre, l'API è comprensibile: il bot si rivolge a un URL specifico con parametri, e Telegram risponde con un oggetto JSON.

Problemi correlati: se in qualche modo misterioso prendi un codice da un oggetto JSON e lo invii per eseguirlo (senza volerlo) – il codice verrà eseguito da te.

Il processo di creazione è descritto in due articoli precedenti, ma ripeto: in Telegram apriamo i contatti, cerchiamo @botfather, gli diciamo /newbot, creeremo il bot Botfortest12344321, lo chiameremo Mynext1234bot, e riceveremo un messaggio con una chiave unica del tipo 1234544311:AbcDefNNNNNNNNNNNNN

Conserva la chiave e non condividerla!

Dopo, puoi configurare il bot, ad esempio vietando che venga aggiunto ai gruppi, ma all'inizio non è necessario.

Chiederemo a BotFather «/mybot» e correggeremo le impostazioni se qualcosa non ci piace.

Apriremo di nuovo i contatti, cercheremo lì @Botfortest12344321 (iniziare sempre la ricerca con @), faremo clic su «inizia» e scriveremo al bot «/Glory to the robots». Il simbolo / è obbligatorio, le virgolette – non sono necessarie.
Il bot, ovviamente, non risponderà.

Controlliamo che il bot sia stato creato – apriamo.

api.telegram.org/bot1234544311:AbcDefNNNNNNNNNNNNN/getMe
dove 1234544311:AbcDefNNNNNNNNNNNNN – è la chiave ottenuta in precedenza,
e otterremo una stringa del tipo
{«ok»:true,«result»:{«»}}

Abbiamo la prima frase segreta (token). Ora dobbiamo scoprire il secondo numero segreto: l'ID della chat con il bot. Ogni chat, gruppo e così via è unico e ha il proprio numero (a volte con un segno meno - per i gruppi aperti). Per scoprire questo numero, dobbiamo richiedere nel browser (in realtà non è assolutamente necessario usare un browser, ma per una migliore comprensione può essere un buon inizio) l'indirizzo (dove 1234544311:NNNNNNNNN è il tuo token

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

e ottenere una risposta del tipo

{«ok»: true, «result»: [{«update_id»: …, … chat«:{«id»:123456789

Ci serve proprio chat_id.

Controlliamo se possiamo scrivere nella chat manualmente: richiamiamo dal browser l'indirizzo

https://api.telegram.org/botvostrotoken/sendMessage?chat_id=123456789&text="La vita è un movimento diretto"

Se hai ricevuto un messaggio dal bot nella tua chat, va bene, puoi passare alla fase successiva.

In questo modo (tramite il browser) puoi sempre controllare dove sono i problemi: se con la generazione del link o se c'è qualche restrizione che non funziona.

Cosa devi sapere prima di continuare a leggere

In Telegram ci sono diversi tipi di chat di gruppo (aperte, chiuse). Per queste chat alcune funzionalità (ad esempio, id) differiscono, il che a volte causa alcuni problemi.

Consideriamo che siamo alla fine del 2019 e persino il nostro eroe dei tempi moderni, il noto Uomo-Orchestra (amministratore, giurista, esperto di sicurezza informatica, programmatore e praticamente MVP) Evgeny V. distingue la variabile $i da un array, ha padroneggiato i cicli e chissà, nei prossimi due anni apprenderà anche Chocolatey, e poi arriverà a Parallel processing with PowerShell e ForEach-Object Parallel ci arriverà.

1. Pensiamo a cosa farà il nostro bot.

Non avevo idee chiare, ho dovuto riflettere. Ho già creato un bot per prendere appunti. Non volevo creare un bot che "invia qualcosa da qualche parte". Per connettersi ad Azure è necessaria una carta di credito, ma da dove può averla uno studente? Va detto che non è così male: i principali servizi cloud offrono un periodo di prova gratuito (ma è comunque necessaria una carta di credito — e verrà addebitato, sembra, un dollaro. Non ricordo se poi sia stato restituito.)

Senza AI ML non è così interessante fare un bot-poeta.

Ho deciso di creare un bot che mi ricordi (o non a me) le parole inglesi dal dizionario.
Il dizionario, per non doversi occupare di un database, sarà contenuto in un file di testo e aggiornato manualmente.
In questo caso, l'obiettivo è mostrare le basi del lavoro, non creare un prodotto anche solo parzialmente pronto.

2. Proviamo cosa e come per la prima volta

Creiamo la cartella C:poshtranslate
Per cominciare, diamo un'occhiata a cosa abbiamo per PowerShell, avviamo ISE tramite esegui
powershell ise
oppure troviamo PowerShell ISE nei programmi installati.
Dopo aver avviato, si aprirà un normale e consueto «qualche editor», se non ci fosse un campo di testo, si può sempre cliccare su «File — crea nuovo».

Controlliamo la versione di PowerShell — scriviamo nel campo di testo:

get-host 

e premiamo F5.

PowerShell ci chiederà di salvare — «Lo script che stai per eseguire sarà salvato.», accettiamo e salviamo in C:poshtranslate il file di PowerShell con il nome myfirstbotBT100.

Dopo l'esecuzione, nella finestra di testo inferiore otterremo una tabella di dati:

Nome             : Windows PowerShell ISE Host
Versione          : 5.1.(e così via)

Ho 5.1 con qualcosa, questo è sufficiente. Se hai un vecchio Windows 7/8, non è un problema — anche se PowerShell deve essere aggiornato alla versione 5 — per esempio, tramite guida.

Digitiamo nella riga di comando sottostante Get-Date, premiamo Invio, controlliamo l'ora, andiamo nella cartella principale con il comando
cd
e puliamo lo schermo con il comando cls (no, non usare rm)

Ora verifichiamo cosa e come funziona — scriviamo non un codice, ma due righe e proviamo a capire cosa fanno. Commentiamo la riga con get-host con il simbolo # e scriviamo un po' di più.

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

(Curioso. Nel menu a discesa per la formattazione del codice su Habr ci sono una ventina di opzioni — ma non c'è PowerShell. C'è Dos. C'è Perl.)

E eseguiamo il codice, premendo F5 o «>» dall'interfaccia grafica.

Otterremo l'output:

Sabato, 8 dicembre 2019 21:00:50 PM (o qualcosa di simile)

Ora analizziamo queste due righe e alcuni punti interessanti, per non tornarci sopra in seguito.

A differenza di Pascal (e non solo), PowerShell cerca di determinare da solo quale tipo assegnare alla variabile, se ne parla nel seguente articolo Guida alla tipizzazione nei linguaggi di programmazione
Pertanto, creando la variabile $TimeNow e assegnandole il valore della data e ora attuali (Get-Date), non dobbiamo preoccuparci troppo di quale tipo di dati venga utilizzato.

Certo, non sapere può portare a problemi, ma questo è un altro discorso. Di seguito nel testo ci sarà un esempio.
Controlliamo cosa abbiamo ottenuto. Eseguiamo (nella riga di comando)

$TimeNow | Get-member

e otterremo una pagina di testo incomprensibile

Esempio di testo incomprensibile numero 1

PS C:&gt; $TimeNow | Get-member
   TypeName: System.DateTime
Name                 MemberType     Definition                                                                                                                                       
----                 ----------     ----------                                                                                                                                       
Add                  <b>Metodo         </b>datetime Aggiungi(timespan valore)  
..
DisplayHint          NotaProprietà   DisplayHintType DisplayHint=DateTime                                                                                                             
Data                 <b>Proprietà       </b>datetime Data {get;}                                                                                                                             
Anno                 Proprietà       int Anno {get;}   
..                                                                                                                               
DateTime             ScriptProperty System.Object DateTime {get=if ((&amp; { Set-StrictMode -Version 1; $this.DisplayHint }) -ieq  "Date")...                                         

Come si può vedere, è stata creata una variabile di tipo TypeName: System.DateTime con un sacco di metodi (nel senso, cosa possiamo fare con questo oggetto variabile) e proprietà.

Chiamiamo $TimeNow.DayOfYear — otteniamo il numero del giorno dell'anno.
Chiamiamo $TimeNow.DayOfYear | Get-Member — otteniamo TypeName: System.Int32 e un gruppo di metodi.
Chiamiamo $TimeNow.ToUniversalTime() — e otteniamo l'orario in UTC

Debugger

A volte è necessario eseguire un programma fino a una certa riga e controllare lo stato del programma in quel momento. A questo scopo, in ISE c'è la funzione Debug — attiva/disattiva il punto di interruzione.
Imposta un punto di interruzione da qualche parte a metà, esegui queste due righe e osserva come appare l'interruzione.

3. Analizziamo l'interazione con il bot di Telegram

Certo, su come interagire con il bot, su tutti i getpush e così via, è stata scritta ancora più letteratura, tuttavia la questione teorica può essere considerata facoltativa.

Nel nostro caso è necessario:

  • Imparare a inviare qualcosa nella chat
  • Imparare a ricevere qualcosa dalla chat

3.1 Iniziamo a inviare qualcosa nella chat e a riceverlo

Un po' di codice — parte 3

Write-output "Questo è la parte 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 = "La vita è un movimento diretto - " + $TimeNow

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

Invoke-WebRequest -Uri $URL4SEND

e in RF in questo punto otteniamo l'errore Unable to connect to the remote server.

Oppure non otteniamo — dipende dall'operatore di rete e da come è configurato e funziona il proxy
Bene — resta da aggiungere il proxy. Tieni presente — l'uso di proxy non crittografati e in generale di proxy non affidabili è estremamente rischioso per la tua sicurezza.

La ricerca di un proxy funzionante non è molto complicata — la maggior parte dei proxy http pubblicati funziona. Il mio ha funzionato, credo, il quinto tentativo.

La sintassi con l'uso del proxy:

Invoke-WebRequest -Uri $URL4SEND -Proxy $MyProxy

Se hai ricevuto un messaggio nella tua chat con il bot — tutto va bene, puoi andare avanti. Se non lo hai ricevuto — continua il debug.

Puoi vedere in cosa si trasforma la tua stringa $URL4SEND e provare a richiederla nel browser, per esempio in questo modo:

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

3.2 Abbiamo imparato a scrivere "qualcosa" nella chat, ora proviamo a leggere

Aggiungiamo altre 4 righe e vediamo cosa c'è dentro tramite | 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

La cosa più interessante ci viene fornita da

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

Diamo un'occhiata a cosa c'è dentro:

Write-Host "ParsedHtml"
$MyMessageGet.ParsedHtml # qui c'è qualcosa di interessante
Write-Host "RawContent"
$MyMessageGet.RawContent # e qui c'è qualcosa di interessante, ma anche leggibile.
Write-Host "Content"
$MyMessageGet.Content

Se tutto funziona, riceverete una lunga stringa del tipo:

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

Per fortuna, in un articolo precedente sul bot Telegram per amministratori di sistema questa stringa (sì, secondo $MyMessageGet.RawContent | get-member — è un System.String), è già stata analizzata.

4. Elaborare il contenuto ricevuto (mandare qualcosa già sappiamo farlo)

Come già scritto qui, la cosa più importante si trova nel content. Diamo un'occhiata più da vicino.

Iniziamo a scrivere al bot un paio di frasi tramite interfaccia web o telefonino

/message1
/message2
/message3

e guardiamo tramite browser l'indirizzo che si è formato nella variabile $URLGET.

Vedremo qualcosa come:

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

Che cos'è? Un oggetto complesso di array di oggetti, contenente un identificatore del messaggio, un identificatore della chat, un identificatore dell'invio e molte altre informazioni.

Tuttavia, non è necessario analizzare "che cos'è questo oggetto" — parte del lavoro è già stata svolta per noi. Diamo un'occhiata a cosa c'è dentro:

Leggiamo i messaggi ricevuti o parte 4

Write-Host "Questa è la parte 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. E ora, cosa facciamo con questo

Salviamo il file ottenuto con il nome myfirstbotBT105 o come preferite, cambiamo il titolo e commentiamo tutto il codice già scritto con

<#start comment 105 end comment 105#>

Ora dobbiamo decidere da dove prendere il dizionario (beh, dove — sul disco in un file) e come sarà strutturato.

Certo, potremmo inserire un enorme dizionario direttamente nel testo dello script, ma non ha senso.
Quindi vediamo con cosa può lavorare PowerShell di default.
In realtà, non importa con quale file lavorare, importa a noi.
Abbiamo a disposizione: txt (va bene, ma perché farlo?), csv, xml.
O possiamo dare un'occhiata a tutti. Vediamo tutti.
Creiamo la classe MyVocabClassExample1 e la variabile $MyVocabExample1
Nota che la classe si scrive senza il simbolo $

un po' di codice #5

write-host "Questo è il quinto capitolo"
class MyVocabClassExample1 {
    [string]$Original  # parola
    [string]$Transcript
    [string]$Translate
    [string]$Example
    [int]$VocWordID # un aspetto molto interessante. L'uso di int con le sue limitazioni può a volte portare a conseguenze drastiche, per esempio, un recente caso con SSD HPE. Inizialmente non avevo aggiunto questo elemento, poi l'ho comunque scritto e commentato.
    }

$MyVocabExample1 = [MyVocabClassExample1]::new()
$MyVocabExample1.Original = "Mela"
$MyVocabExample1.Transcript = "[ ˈapəl ]"
$MyVocabExample1.Translate = "Mela"
$MyVocabExample1.Example = "Una mela è un frutto dolce e commestibile prodotto da un melo (Malus domestica)"
# $MyVocabExample1.$VocWordID = 1

$MyVocabExample2 = [MyVocabClassExample1]::new()
$MyVocabExample2.Original = "Pera"
$MyVocabExample2.Transcript = "[ pe(ə)r ]"
$MyVocabExample2.Translate = "Pera"
$MyVocabExample2.Example = "L'albero e il cespuglio di pera sono una specie del genere Pyrus"
# $MyVocabExample1.$VocWordID = 2

Proviamo a scrivere questo su file secondo il modello.

Un po' di codice #5.1

Write-Host $ScriptDir # spero che $ScriptDir non lo abbiate commentato 
$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

— e riceveremo un errore sulla riga Out-File -FilePath $MyFilenameExample01 -InputObject -Append $MyVocabExample2.

Non vuole aggiungere, ah-ah che peccato.

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

Vediamo cosa è uscito. Un aspetto testuale magnifico — ma come esportare di nuovo da esso? È necessario inserire dei separatori di testo, per esempio le virgole?

E alla fine ottenere "un file con separatori — virgole, valori separati da virgole (CSV) A FERMATEVI UN ATTIMO.
#

$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 

È facile notare che, MS non si è particolarmente distinta in logica, per procedure simili in un caso si usa -FilePath, per l'altro -Path.

Inoltre, nel terzo file è scomparso il russo, nel quarto file è venuto fuori… beh, qualcosa è uscito. #TYPE System.Object[] 00
# „Count“,»Length»,«LongLength»,«Rank»,«SyncRoot»,«IsReadOnly»,«IsFixedSize»,«IsSynchronized»
#
Riscriviamo un po':

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

Sembra aver aiutato — ma il formato non mi piace comunque.

Particolarmente non mi piace il fatto che non posso inserire direttamente le righe dell'oggetto in un file.
A proposito, dato che abbiamo iniziato a scrivere nei file, potremmo cominciare a mantenere un log di avvio? Abbiamo già il tempo come variabile e sappiamo impostare il nome del file.

Scrivere, ovviamente, al momento non c'è nulla, ma possiamo pensare a come gestire meglio la rotazione dei log.
Proviamo con xml.

Un po' di 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

L'esportazione in xml ha solo vantaggi: leggibilità, esportazione dell'intero oggetto e non è necessario eseguire l'uppend.

Proviamo a leggere il file xml.

Un po' di lettura da xml

$MyFilenameExample06 = $ScriptDir + "Example06.xml"
$MyVocabExample4AsArray = Import-Clixml -Path $MyFilenameExample06
# $MyVocabExample4AsArray 
# $MyVocabExample4AsArray[0]
# e un po' di dettagli poco evidenti. Powershell a volte si comporta in modo inaspettato.
# Ad esempio, queste due uscite sono diverse
# Write-Output $MyVocabExample4AsArray 
# write-host $MyVocabExample4AsArray 

Tornando al compito. Abbiamo scritto un file di prova, l'abbiamo letto, il formato di archiviazione è chiaro, se necessario, possiamo scrivere un piccolo editor di file per aggiungere e rimuovere righe.

Ricordo che il compito era creare un piccolo bot di apprendimento.

Formato di lavoro: io mando al bot il comando “esempio”, il bot mi manda una parola scelta a caso e la trascrizione, e dopo 10 secondi mi invia la traduzione e il commento. Sappiamo leggere i comandi, dovremmo anche imparare a selezionare e verificare automaticamente i proxy e resettare i contatori dei messaggi.

Decommenteremo tutto ciò che è stato precedentemente commentato come non necessario, commenteremo gli esempi con txt e csv diventati superflui, e salveremo il file come versione B106

Ah, sì. Invieremo qualcosa al bot di nuovo.

6. Invio da funzioni e non solo

Prima di elaborare la ricezione, dobbiamo creare una funzione di invio per “qualcosa”, oltre al messaggio di test.

Certo, nel nostro esempio avremo solo un invio e solo un'elaborazione, e se avessimo bisogno di fare la stessa cosa più volte?

È più semplice scrivere una funzione. Quindi, abbiamo una variabile di tipo oggetto $MyVocabExample4AsArray, letta dal file, sotto forma di un array di ben due elementi.
Iniziamo a leggere.

Allo stesso tempo, ci occupiamo degli orologi, ci serviranno dopo (in realtà in questo esempio non serviranno 🙂

Un po' di codice #6.1

Scrivi-Output "Questa è la Parte 6"
$Timezone = (Get-TimeZone)
SE($Timezone.SupportsDaylightSavingTime -eq $True){
    $TimeAdjust =  ($Timezone.BaseUtcOffset.TotalSeconds + 3600) } # ora legale
    ALTRIMENTI{$TimeAdjust = ($Timezone.BaseUtcOffset.TotalSeconds) 
    }
    
funzione MyFirstFunction($SomeExampleForFunction1){
$TimeNow = Get-Date
$TimeNow.ToUniversalTime()
# $MyText02 = $TimeNow + " " + $SomeExampleForFunction1 # e qui avremo un errore
$MyText02 = $SomeExampleForFunction1 + " " + $TimeNow # e qui non ne avremo, chi indovina perché - quello è bravo.

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

Come è facile vedere, nella funzione vengono richiamati $MyToken e $MyChatID, che sono assegnati precedentemente.

Non si dovrebbe fare così, e se $MyToken è unico per ogni bot, $MyChatID cambierà a seconda della chat.

Tuttavia, poiché questo è un esempio, per ora lo ignoreremo.

Poiché $MyVocabExample4AsArray non è un array, anche se sembra molto simile, quindi non si può semplicemente prendere e richiederne la lunghezza.

Dovremo fare ancora una volta qualcosa che non si dovrebbe fare - atterrare non secondo il codice - contare

Un po' di codice #6.2

$MaxRandomExample = 0 
foreach ($Obj in $MyVocabExample4AsArray) {
$MaxRandomExample ++
}
Scrivi-Output $MaxRandomExample
$RandomExample = Get-Random -Minimum 0 -Maximum ($MaxRandomExample)
$TextForExample1 = $MyVocabExample4AsArray[$RandomExample].Original
# MyFirstFunction($TextForExample1)
# o in una sola riga
# MyFirstFunction($MyVocabExample4AsArray[Get-Random -Minimum 0 -Maximum ($MaxRandomExample -1)].Example)
# Indovinate da soli quale esempio è più leggibile per le persone esterne.

Random una funzione interessante. Supponiamo di voler ottenere 0 o 1 (abbiamo solo due elementi nell'array). Impostando i limiti a 0..1, otterremo "1"?
no - non lo otterremo, abbiamo appositamente fornito l'esempio Example 2: Ottieni un intero casuale tra 0 e 99 Get-Random -Maximum 100
Quindi per 0..1 dovremo impostare la dimensione su 0..2, con il numero massimo dell'elemento = 1.

7. Elaborazione dei messaggi ricevuti e lunghezza massima della coda

A cosa ci eravamo fermati? abbiamo la variabile ricevuta $MyMessageGet
e quella ricevuta da essa $Content4Pars01, di cui ci interessano gli elementi dell'array Content4Pars01.result

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

Invieremo al bot /message10, /message11, /message12, /word e anche di nuovo /word e /ciao.
Vediamo cosa abbiamo ottenuto:

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

Esamineremo tutto ciò che abbiamo ricevuto e risponderemo se il messaggio era /word
la struttura case of, ciò che alcuni descrivono come if-elseif, in powershell viene chiamata attraverso switch. Nel codice sottostante è stata utilizzata la chiave -wildcard, il che non è affatto necessario e potrebbe addirittura essere dannoso.

Un po' di codice #7.1

Write-Output "Questo è il capitolo 7"
Foreach ($Result in $Content4Pars01.result) # Sì, si può fare più velocemente 
 { 
    switch -wildcard ($Result.message.text) 
            {
            "\/word" {MyFirstFunction($TextForExample1)}
            }
}

Eseguiremo lo script un paio di volte. Otterremo la stessa parola due volte per ogni tentativo di esecuzione, specialmente se abbiamo sbagliato implementando random.

Ma aspetta. Non abbiamo inviato \/word di nuovo, come mai il messaggio viene elaborato di nuovo?

La coda per inviare messaggi al bot ha una lunghezza finita (sembra 100 o 200 messaggi), e deve essere svuotata manualmente.

Questo è ovviamente descritto nella documentazione, ma bisogna leggerla!

In questo caso abbiamo bisogno del parametro ?chat_id, mentre &timeout, &limit, &parse_mode=HTML e &disable_web_page_preview=true non sono ancora necessari.

Documentazione su telegram api si trova qui
In inglese è scritto chiaramente:
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. The negative offset can be specified to retrieve updates starting from -offset update from the end of the updates queue. All previous updates will forgotten.

Diamo un'occhiata a:

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

E resettiamo — riscriveremo un po' la funzione. Abbiamo due opzioni: passare alla funzione l'intero messaggio e trattarlo completamente nella funzione, oppure passare solo l'ID del messaggio e resettarlo. Per esempio, la seconda opzione sembra più semplice.

In precedenza, la nostra stringa di richiesta per "tutti i messaggi" sembrava come

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

ma apparirà come

$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 

Nessuno vieta di ottenere prima tutti i messaggi, elaborarli, e solo dopo un'elaborazione riuscita richiedere unconfirmed -> confirmed.

Perché ha senso invocare la conferma dopo aver completato tutte le elaborazioni? Può verificarsi un errore a metà esecuzione, e se per esempio per un chatbot gratuito ignorare un messaggio singolo non è un grosso problema, quando stai trattando un salario o una transazione con carta, il risultato può essere peggiore.

Ancora un paio di righe di codice

$LastMessageId = ($Content4Pars01.result | select -last 1).update_id  #l'errore in questo punto si suppone venga corretto autonomamente. 
$URLGET1 = "https://api.telegram.org/bot$mytoken/getUpdates?offset=$LastMessageId&limit=100" 
Invoke-WebRequest -Uri $URLGET1 -Method Get -Proxy $MyProxy

8. In conclusione

Le funzioni principali — lettura dei messaggi, svuotamento della coda, lettura da file e scrittura su file sono state completate e mostrate.

Restano solo quattro cose da fare:

  • invio della risposta corretta alla richiesta in chat
  • invio della risposta in QUALSIASI chat in cui è stato aggiunto il bot
  • esecuzione del codice in un ciclo
  • avvio del bot dal pianificatore di Windows.

Tutti questi compiti sono semplici e possono essere facilmente realizzati leggendo la documentazione su parametri come
Set-ExecutionPolicy Unrestricted e -ExecutionPolicy Bypass
ciclo di tipo

$TimeToSleep = 3 # interrogazione ogni 3 secondi
$TimeToWork = 10 # minuti
$HowManyTimes = $TimeToWork*60/$TimeToSleep # contatore per il ciclo
$MainCounter = 0
for ($MainCounter=0; $MainCounter -le $HowManyTimes) {
sleep $TimeToSleep
$MainCounter ++

Grazie a tutti coloro che hanno letto fino alla fine.

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster