Modello per un semplice bot di Telegram per gli scolari delle classi 7-9 utilizzando Powershell

Durante le conversazioni con un amico, ho improvvisamente appreso che ai bambini delle classi 8-10 della loro scuola non viene insegnata affatto la programmazione. Word, Excel e tutto. Nessun logo, nemmeno Pascal, nemmeno VBA per Excel.

Sono rimasto molto sorpreso, ho aperto Internet e ho iniziato a leggere -
Uno dei compiti di una scuola specializzata è promuovere l'educazione di una nuova generazione che soddisfi le condizioni della società dell'informazione nel suo livello di sviluppo e stile di vita.
Il corso consentirà agli studenti di consolidare nella pratica la conoscenza dei costrutti base del linguaggio di programmazione Pascal. (dal programma di alcune palestre per il 2017)

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

Sotto il taglio c'è come scrivere un altro semplice bot in Powershell e farlo funzionare senza webhook, IP bianchi, server dedicati, macchine virtuali distribuite nel cloud e così via, su un normale PC domestico con Windows normale.

TLDR: Un altro articolo noioso con errori grammaticali e fattuali, niente da leggere, niente umorismo, niente immagini.

Non c'è niente di nuovo nell'articolo, quasi tutto quello che è stato scritto prima è già stato su Habré, ad esempio negli articoli Istruzioni: come creare bot in Telegram и Bot di Telegram per amministratore di sistema.
Inoltre l’articolo è volutamente ridondante per non fare ogni volta riferimento alla letteratura didattica. Nel testo non ci sono riferimenti a Gang 4, PowerShell Deep Dives o, ad esempio, ai 5 pilastri del Canone di architettura AWS.

Invece di una prefazione, puoi saltare

Sentiti libero di saltareNel 2006, Microsoft ha rilasciato PowerShell 1.0 per gli allora Windows XP, Vista e Server 2003. In un certo senso, ha sostituito elementi come script cmdbat, script vb, Windows Script Host e JScript.

Anche adesso, PowerShell può essere considerato solo come il passo successivo dopo le opzioni Logo, al posto del Delphi, probabilmente ancora utilizzato (o qualcosa di più vecchio), nonostante la presenza di loop, classi, funzioni, chiamate MS GUI, Integrazione con Git e così via.

Powershell viene utilizzato relativamente raramente; puoi incontrarlo solo sotto forma di PowerShell Core, VMware vSphere PowerCLI, Azure PowerShell, MS Exchange, Desired State Configuration, Accesso Web a PowerShell e una dozzina circa di programmi e funzioni usati più raramente. Forse avrà una seconda ventata con il rilascio WSL2, ma non è esattamente.

Powershell presenta anche tre grandi vantaggi:

  1. È relativamente semplice, c'è molta letteratura ed esempi a riguardo, e anche in russo, ad esempio, un articolo su Foreach - dal libro PowerShell in modo approfondito - sulla differenza () e {}
  2. Va con l'editore ISE, incluso con Windows. C'è anche una sorta di debugger lì.
  3. È facile chiamarlo componenti per la costruzione di un'interfaccia grafica.

0. Preparazione.

Abbiamo bisogno di:

  • PC Windows (ho Windows 10)
  • Almeno un qualche tipo di accesso a Internet (ad esempio tramite NAT)
  • Per coloro che hanno un accesso limitato a Telegram: freegate installato e configurato nel browser, in alcuni casi difficili, insieme a Simple DNS Crypt
  • Avere un client Telegram funzionante sul tuo telefono
  • Comprendere le nozioni di base: cos'è una variabile, un array, un ciclo.

Articoli aperti e letti - Istruzioni: come creare bot in Telegram и Bot di Telegram per amministratore di sistema

1. Creiamo un altro bot di prova.

Dato che tutti lo sanno già ed è già successo, puoi anche saltarloCome indicato nell'articolo sopra - Innanzitutto un bot per Telegram - è ancora un'applicazione in esecuzione dalla tua parte e che effettua richieste all'API Bot di Telegram. Inoltre, l'API è chiara: il bot accede a un URL specifico con parametri e Telegram risponde con un oggetto JSON.

Problemi correlati: se in qualche modo sconosciuto prendi del codice da un oggetto JSON e in qualche modo lo invii per l'esecuzione (non di proposito), il codice verrà eseguito per te.

Il processo di creazione è descritto nei due articoli sopra, ma ripeto: in un telegramma apriamo i contatti, cerchiamo @botfather, gli diciamo /newbot, creiamo un bot Botfortest12344321, lo chiamiamo Mynext1234bot, e riceviamo un messaggio con una chiave univoca del modulo 1234544311:AbcDefNNNNNNNNNNNNNN

Abbi cura della chiave e non regalarla!

Quindi puoi configurare il bot, ad esempio, vietarne l'aggiunta ai gruppi, ma nei primi passaggi ciò non è necessario.

Chiediamo a BotFather "/mybot" e regoliamo le impostazioni se qualcosa non ci piace.

Riapriamo i contatti, troviamo lì @Botfortest12344321 (è obbligatorio iniziare la ricerca con @), clicchiamo su “start” e scriviamo al bot “/Gloria ai robot”. Il segno / è obbligatorio, le virgolette non sono necessarie.
Il bot, ovviamente, non risponderà a nulla.

Controlliamo che il bot sia stato creato e apriamolo.

api.telegram.org/bot1234544311:AbcDefNNNNNNNNNNNNNN/getMe
dove 1234544311:AbcDefNNNNNNNNNNNNNN è la chiave ricevuta in precedenza,
e ottieni una riga come
{"ok":true,"risultato":{""}}

Abbiamo la prima frase segreta (token). Ora dobbiamo scoprire il secondo numero segreto: l'ID della chat con il bot. Ogni chat, gruppo, ecc. è individuale e ha il proprio numero (a volte con un segno meno - per i gruppi aperti). Per scoprire questo numero dobbiamo richiedere nel browser (in effetti nel browser non è affatto necessario, ma per una migliore comprensione puoi iniziare con esso) l'indirizzo (dove 1234544311:NNNNNNNNNN è il tuo token

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

e ottieni una risposta come

{"ok":true,"risultato":[{"update_id":...,... chiacchierare":{"id":123456789

Abbiamo bisogno di chat_id.

Verifichiamo di poter scrivere manualmente alla chat: chiamiamo l'indirizzo dal browser

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

Se ricevi un messaggio da un bot nella tua chat, ok, passi alla fase successiva.

In questo modo (tramite il browser) puoi sempre verificare se ci sono problemi con la generazione dei link, oppure se qualcosa è nascosto da qualche parte e non funziona.

Cosa devi sapere prima di continuare a leggere

Telegram ha diversi tipi di chat di gruppo (aperte, chiuse). Per queste chat, alcune funzioni (ad esempio l'id) sono diverse, il che a volte causa alcuni problemi.

Supponiamo che sia la fine del 2019 e che anche l'eroe del nostro tempo, il noto Man-Orchestra (amministratore, avvocato, specialista in sicurezza informatica, programmatore e praticamente MVP) Evgeniy V. distingue la variabile $i da un array, ha imparato i loop, guarda che nei prossimi due anni padroneggerà Chocolatey, e poi Elaborazione parallela con PowerShell и Parallelo per ogni oggetto verrà.

1. Pensiamo a cosa farà il nostro bot

Non avevo idee, dovevo pensare. Ho già scritto un bot-notebook. Non volevo creare un bot “che invii qualcosa da qualche parte”. Per connettersi ad Azure serve una carta di credito, ma dove la prende lo studente? Va notato che non tutto è così male: le nuvole principali danno una sorta di periodo di prova gratuitamente (ma hai ancora bisogno di un numero di carta di credito - e sembra che verrà addebitato un dollaro. Non ricordo se è stato restituito più tardi.)

Senza AI ML non è così interessante creare un bot-povero-poeta-tessitore.

Ho deciso di creare un bot che mi ricorderà (o non mi ricorderà) le parole inglesi del dizionario.
Per evitare di manomettere il database, il dizionario verrà archiviato in un file di testo e aggiornato manualmente.
In questo caso, il compito è mostrare le basi del lavoro e non realizzare almeno un prodotto parzialmente finito.

2. Provare cosa e come per la prima volta

Creiamo una cartella C:poshtranslate
Innanzitutto, vediamo che tipo di PowerShell abbiamo, avviamo ISE tramite start-run
powershell ise
oppure trova Powershell ISE nei programmi installati.
Dopo il lancio, si aprirà il solito familiare "una specie di editor", se non è presente un campo di testo, puoi sempre fare clic su "File - crea nuovo".

Diamo un'occhiata alla versione di PowerShell: scrivi nel campo di testo:

get-host 

e premi F5.

Powershell offrirà di salvare: "Lo script che stai per eseguire verrà salvato.", siamo d'accordo e salviamo il file da PowerShell con il nome in C: poshtranslate myfirstbotBT100.

Dopo il lancio, nella finestra di testo inferiore otteniamo una tabella dati:

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

Ho 5.1 qualcosa, basta. Se hai un vecchio Windows 7/8, non è un grosso problema, anche se PowerShell dovrà essere aggiornato alla versione 5, ad es. istruzione.

Digita Get-Date nella riga di comando sottostante, premi Invio, guarda l'ora, vai alla cartella principale con il comando
cd
e cancella lo schermo con il comando cls (no, non è necessario usare rm)

Ora controlliamo cosa funziona e come: non scriviamo nemmeno il codice, ma due righe, e cerchiamo di capire cosa fanno. Commentiamo la riga con get-host con il simbolo # e aggiungiamo qualcosa.

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

(La cosa interessante è che nell'elenco a discesa della formattazione del codice su Habré ci sono due dozzine di opzioni, ma Powershell non è presente. Dos è presente. Perl è presente.)

Ed eseguiamo il codice premendo F5 o ">" dalla GUI.

Otteniamo il seguente output:

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

Ora diamo un’occhiata a queste due righe e ad alcuni punti interessanti per non tornare su questo in futuro.

A differenza di Pascal (e non solo), PowerShell stessa cerca di determinare quale tipo assegnare ad una variabile; maggiori dettagli a riguardo sono scritti nell'articolo Programma didattico sulla digitazione nei linguaggi di programmazione
Pertanto, creando una variabile $TimeNow e assegnandole il valore della data e dell'ora correnti (Get-Date), non dobbiamo preoccuparci troppo del tipo di dati che saranno presenti.

È vero, questa ignoranza potrebbe far male in seguito, ma sarà per dopo. Di seguito nel testo ci sarà un esempio.
Vediamo cosa abbiamo ottenuto. Eseguiamo (sulla riga di comando)

$TimeNow | Get-member

e ottieni una pagina di testo incomprensibile

Esempio di testo incomprensibile numero 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")...                                         

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

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

Debug

A volte capita che sia necessario eseguire un programma fino ad una certa riga e vedere lo stato del programma in quel momento. A questo scopo, ISE dispone di una funzione Debug: attiva/disattiva il punto di interruzione
Metti un punto di interruzione da qualche parte nel mezzo, esegui queste due righe e guarda come appare l'interruzione.

3. Comprendere l'interazione con il bot di Telegram

Naturalmente è stata scritta ancora più letteratura sull'interazione con il bot, con tutti i getpush e così via, ma la questione teorica può essere considerata facoltativamente.

Nel nostro caso è necessario:

  • Impara a inviare qualcosa in corrispondenza
  • Impara a ottenere qualcosa dalla corrispondenza

3.1 Imparare a inviare qualcosa nella corrispondenza e ricevere da essa

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

e nella Federazione Russa a questo punto riceviamo l'errore Impossibile connettersi al server remoto.

Oppure non lo riceviamo, dipende dall'operatore delle telecomunicazioni e se il proxy è configurato e funzionante
Bene, non resta che aggiungere un proxy. Tieni presente che l'utilizzo di un proxy non crittografato e generalmente fraudolento è estremamente pericoloso per la tua salute.

Il compito di trovare un proxy funzionante non è molto difficile: la maggior parte dei proxy http pubblicati funziona. Penso che il quinto abbia funzionato per me.

Sintassi utilizzando proxy:

Invoke-WebRequest -Uri $URL4SEND -Proxy $MyProxy

Se ricevi un messaggio nella tua chat con un bot, allora va tutto bene, puoi andare avanti. In caso contrario, continua il debug.

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

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

3.2. Abbiamo imparato a scrivere “qualcosa” in chat, ora proviamo a leggerlo

Aggiungiamo altre 4 righe e vediamo cosa c'è dentro attraverso | get-membro

$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

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

Vediamo cosa contengono:

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

Se tutto funziona per te, otterrai una lunga fila come:

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

Fortunatamente, nell'articolo precedentemente pubblicato sul bot di Telegram per l'amministratore di sistema questa riga (sì, secondo $MyMessageGet.RawContent | get-member è System.String), è già stato smontato.

4. Elabora ciò che ricevi (sappiamo già come inviare qualcosa)

Come già scritto qui, le cose più necessarie risiedono nel contenuto. Diamo un'occhiata più da vicino.

Innanzitutto, scriveremo un altro paio di frasi al bot dall'interfaccia web o dal telefono

/message1
/message2
/message3

e guarda attraverso il browser l'indirizzo formato nella variabile $URLGET.

Vedremo qualcosa del tipo:

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

Cos'è? Alcuni oggetti complessi da matrici di oggetti contenenti un identificatore di messaggio end-to-end, un identificatore di chat, un identificatore di invio e molte altre informazioni.

Tuttavia, non abbiamo bisogno di capire "che tipo di oggetto è questo": parte del lavoro è già stata fatta per noi. Vediamo cosa c'è dentro:

Lettura dei messaggi ricevuti o parte 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. Cosa dovremmo fare adesso?

Salviamo il file risultante con il nome myfirstbotBT105 o come preferisci, cambiamo il titolo e commenta tutto il codice già scritto tramite

<#start comment 105 end comment 105#>

Ora dobbiamo decidere dove trovare il dizionario (beh, dove - sul disco in un file) e come sarà.

Naturalmente, puoi scrivere un dizionario enorme direttamente nel testo della sceneggiatura, ma questo non è assolutamente il punto.
Quindi vediamo con cosa PowerShell può funzionare normalmente.
In generale, a lui non importa con quale file lavorare, a noi non importa.
Abbiamo una scelta: txt (puoi, ma perché), csv, xml.
Possiamo guardare tutti? Vediamo tutti.
Creiamo una classe MyVocabClassExample1 e una variabile $MyVocabExample1
Noto che la classe è scritta senza $

qualche codice #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

Proviamo a scriverlo nei file utilizzando esemplare.

Alcuni codici #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

- e riceviamo 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 succede. Ottima visualizzazione del testo: ma come esportarlo nuovamente? Dovrei introdurre qualche tipo di separatore di testo, come le virgole?

E alla fine ottieni un file “valori separati da virgole (CSV) A FERMATI ASPETTA.
#

$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 

Come è facile vedere, MS non si distingue particolarmente per la sua logica; per una procedura simile, in un caso viene utilizzato -FilePath, nell'altro -Path.

Inoltre nel terzo file è scomparsa la lingua russa, nel quarto file è risultato... beh, è ​​successo qualcosa. #TYPE Sistema.Oggetto[] 00
# “Count”,”Length”,”LongLength”,”Rank”,”SyncRoot”,”IsReadOnly”,”IsFixedSize”,”IsSynchronized”
#
Riscriviamolo 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 ancora non mi piace il formato.

In particolare non mi piace il fatto di non poter inserire direttamente le righe di un oggetto in un file.
A proposito, da quando abbiamo iniziato a scrivere sui file, possiamo iniziare a tenere un registro di avvio? Abbiamo il tempo come variabile, possiamo impostare il nome del file.

È vero, non c'è ancora niente da scrivere, ma puoi pensare a come ruotare al meglio i registri.
Proviamo xml per ora.

Alcuni 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 presenta molti vantaggi: leggibilità, esportazione dell'intero oggetto e nessuna necessità di eseguire un uppend.

Proviamo leggere il file XML.

Una piccola lettura da xml

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

Torniamo al compito. Abbiamo scritto un file di prova, lo leggiamo, il formato di archiviazione è chiaro, se necessario puoi scrivere un piccolo editor di file separato per aggiungere ed eliminare righe.

Lascia che ti ricordi che il compito era creare un piccolo bot di addestramento.

Formato di lavoro: invio il comando "esempio" al bot, il bot mi invia una parola e una trascrizione selezionate casualmente e dopo 10 secondi mi invia una traduzione e un commento. Sappiamo leggere i comandi, vorremmo anche imparare a selezionare e controllare automaticamente i proxy e a resettare i contatori dei messaggi fino all'oblio.

Decommentiamo tutto ciò che in precedenza era stato commentato come non necessario, commentiamo gli esempi ora non necessari con txt e csv e salviamo il file come versione B106

Oh si. Inviamo di nuovo qualcosa al bot.

6. Invio da funzioni e altro

Prima di elaborare la ricezione, è necessario creare una funzione per inviare "almeno qualcosa" diverso da un messaggio di prova.

Naturalmente nell'esempio avremo un solo invio e una sola elaborazione, ma cosa succede se dobbiamo fare la stessa cosa più volte?

È più semplice scrivere una funzione. Abbiamo quindi una variabile di tipo oggetto $MyVocabExample4AsArray, letta dal file, sotto forma di un array di massimo due elementi.
Andiamo a leggere.

Allo stesso tempo, ci occuperemo dell'orologio; ci servirà in seguito (infatti in questo esempio non ci servirà :)

Alcuni codici #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
}

Come puoi facilmente vedere, la funzione chiama $MyToken e $MyChatID, che erano stati codificati in precedenza.

Non è necessario farlo e se $MyToken è uno per ogni bot, $MyChatID cambierà a seconda della chat.

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

Poiché $MyVocabExample4AsArray non è un array, sebbene sia molto simile ad uno, allora non puoi semplicemente prenderlo richiederne la lunghezza.

Ancora una volta dovremo fare qualcosa che non si può fare - paracadute non secondo il codice - prendilo e conta

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

Random caratteristica interessante. Diciamo che vogliamo ricevere 0 o 1 (abbiamo solo due elementi nell'array). Quando impostiamo i limiti 0..1, otterremo “1”?
no, non lo otterremo, abbiamo un esempio speciale Esempio 2: ottieni un numero intero casuale compreso tra 0 e 99 Get-Random -Maximum 100
Pertanto, per 0..1 dobbiamo impostare la dimensione 0..2, con il numero massimo di elementi = 1.

7. Elaborazione dei messaggi in entrata e lunghezza massima della coda

Dove ci siamo fermati prima? abbiamo la variabile ricevuta $MyMessageGet
e $Content4Pars01 da esso ottenuti, di cui a noi interessano gli elementi dell'array Content4Pars01.result

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

Inviamo al bot /message10, /message11, /message12, /word e ancora /word e /hello.
Vediamo cosa abbiamo ottenuto:

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

Esaminiamo tutto ciò che abbiamo ricevuto e inviamo una risposta se il messaggio era /word
il caso del costrutto, quello che alcuni descrivono come if-elseif, è chiamato in PowerShell tramite interruttore. Allo stesso tempo, il codice seguente utilizza la chiave -jolly, che è completamente inutile e persino dannosa.

Alcuni codici #7.1

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

Eseguiamo lo script un paio di volte. Otterremo la stessa parola due volte per ogni tentativo di esecuzione, soprattutto se abbiamo commesso un errore nell'implementazione di random.

Ma fermati. Non abbiamo inviato di nuovo /word, quindi perché il messaggio viene nuovamente elaborato?

La coda per l'invio di messaggi al bot ha una lunghezza finita (100 o 200 messaggi, credo) e deve essere cancellata manualmente.

Questo è ovviamente descritto nella documentazione, ma devi leggerla!

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

Documentazione per l'API di Telegram è qui
Dice in bianco e in inglese:
Identificatore del primo aggiornamento da restituire. Deve essere maggiore di uno rispetto al più alto tra gli identificatori degli aggiornamenti ricevuti in precedenza. Per impostazione predefinita, gli aggiornamenti iniziano dal primo
non confermato vengono restituiti gli aggiornamenti. Un aggiornamento viene considerato confermato non appena getUpdates viene richiamato con an offset superiore rispetto al suo update_id. È possibile specificare l'offset negativo per recuperare gli aggiornamenti a partire da -offset update dalla fine della coda degli aggiornamenti. Tutti gli aggiornamenti precedenti verranno dimenticati.

Guardiamo:

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

Sì, lo ripristineremo e riscriveremo un po' la funzione. Abbiamo due opzioni: passare l'intero messaggio alla funzione ed elaborarlo interamente nella funzione oppure fornire solo l'ID del messaggio e reimpostarlo. Ad esempio, il secondo sembra più semplice.

In precedenza, la nostra stringa di query "tutti i messaggi" assomigliava a

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

e sembrerà

$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 ti vieta di ricevere prima tutti i messaggi, elaborarli e solo dopo aver elaborato con successo la richiesta non confermata -> confermata.

Perché ha senso chiamare la conferma dopo che tutta l'elaborazione è stata completata? È possibile che si verifichi un errore nel bel mezzo dell'esecuzione e, se, ad esempio, per un chatbot gratuito, perdere un singolo messaggio non è niente di speciale, se stai elaborando lo stipendio o la transazione con la carta di qualcuno, il risultato potrebbe essere peggiore.

Ancora un paio di righe di codice

$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. Invece di una conclusione

Vengono eseguite e visualizzate le funzioni di base: lettura dei messaggi, reimpostazione della coda, lettura da file e scrittura su file.

Rimangono solo quattro cose da fare:

  • inviando la risposta corretta ad una richiesta in chat
  • inviando una risposta a QUALSIASI chat a cui è stato aggiunto il bot
  • eseguendo il codice in un ciclo
  • avviare un bot dallo scheduler di Windows.

Tutte queste attività sono semplici e possono essere facilmente eseguite leggendo la documentazione su parametri come
Set-ExecutionPolicy Unrestricted e -ExecutionPolicy Bypass
ciclo della forma

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

Grazie a tutti coloro che hanno letto.

Fonte: habr.com

Aggiungi un commento