Skabelon til den simpleste telegrambot for 7.-9. klasseelever i Powershell

Under conversations with a friend, I suddenly learned that children in grades 8-10 in their school are not taught programming at all. Just Word, Excel, and that's it. No Logo, not even Pascal, nor even VBA for Excel.

I was very surprised, opened the internet and started reading—
One of the tasks of a specialized school is to contribute to the upbringing of a new generation that corresponds to the conditions of the information society in terms of their level of development and way of life.
This course will allow students to apply their knowledge of the main constructs of the Pascal programming language in practice. (from the program of some gymnasium in 2017)

In the end, I decided to spend a couple of hours drafting an example of 'how to create a simple bot for schoolchildren.'

Below is how to write yet another simple bot in PowerShell and make it work without webhooks, public IPs, dedicated servers, deployable virtual machines in the cloud, etc. — on a regular home PC with standard Windows.

TLDR: Another boring article with grammatical and factual errors, nothing to read, no humor, no pictures.

There is nothing new in the article; almost everything written has been mentioned before on Habr, for example, in articles like Instructions: How to create bots in Telegram og Telegram bot for system administrators.
Moreover, the article is deliberately excessive to avoid referencing educational literature every time. There are no references to the Band 4, PowerShell Deep Dives, or say The 5 Pillars of the AWS Well-Architected Framework in the text.

Instead of a preface, we can skip it

We confidently skip itIn 2006, Microsoft released PowerShell 1.0 for the then still popular Windows XP, Vista, and 2003 Server. In some ways, it replaced things like cmd.exe scripts, VB scripts, Windows Script Host, and JScript.

Even now, PowerShell can only be regarded as the next step after Logo variants, instead of what might still be used like Delphi (or something older), despite having loops, classes, functions, and MS GUI calls. Integration with Git og så videre.

PowerShell is comparatively rarely used, you might encounter it only as PowerShell Core, VMware vSphere PowerCLI, Azure PowerShell, MS Exchange, Desired State Configuration, PowerShell Web Access and a dozen or so rarely used programs and functions. Perhaps it will gain new life with the release of WSL2, but that's not certain.

PowerShell has three significant advantages:

  1. Det er relativt simpelt, der findes masser af litteratur og eksempler, endda på russisk, for eksempel en artikel om ForEach – fra en bog PowerShell i dybden – om forskellen imellem () og {}
  2. Det kommer med editoren ISE, i pakken med Windows. Der er endda en slags debugger.
  3. Det kalder nemt komponenter til opbygning af grafiske brugerflader.

0. Forberedelse.

Vi har brug for:

  • En PC med Windows (jeg har Windows 10)
  • En eller anden form for internetadgang (for eksempel via NAT)
  • For dem, der har begrænset adgang til Telegram – en installeret og konfigureret freegate i browseren, i nogle komplekse tilfælde sammen med Symple DNS Crypt
  • En fungerende Telegram-klient på telefonen
  • Forståelse af helt grundlæggende koncepter – hvad er en variabel, et array, en løkke.

Åbne og læste artikler – Instructions: How to create bots in Telegram og Telegram bot for system administrators

1. Lad os oprette en testbot.

Da det stort set er noget, alle ved, og det allerede er blevet gjort, kan det også springes overSom nævnt i artiklen ovenfor – Først og fremmest, en bot til Telegram – er stadig en applikation, der kører på din side og foretager forespørgsler til Telegram Bot API. API'et er klart – bot'en kontakter en bestemt URL med parametre, og Telegram svarer med et JSON-objekt.

Relaterede problemer: hvis du på en eller anden mystisk måde tager en kode fra JSON-objektet og sender den til udførelse (ikke med vilje) – vil koden blive udført hos dig.

Processen med at oprette er beskrevet i de to ovenstående artikler, men lad mig gentage: i Telegram åbner vi kontakter, søger efter @botfather, siger til ham /newbot, opretter bot'en Botfortest12344321, kalder ham Mynext1234bot, og modtager en besked med en unik nøgle i form af 1234544311:AbcDefNNNNNNNNNNNNN

Beskyt nøglen og del den ikke ud!

Derefter kan bot'en konfigureres, for eksempel kan vi forbyde, at den tilføjes til grupper, men det er ikke nødvendigt i de tidlige skridt.

Spørg BotFather "\/mybot" og juster indstillingerne, hvis noget ikke er tilfredsstillende.

Find igen kontakterne der, søg efter @Botfortest12344321 (det er vigtigt at starte søgningen med @), tryk på "start" og skriv til bot'en "\/Ære til robotterne". Symbolet \/ er vigtigt, og citationstegnene er ikke nødvendige.
Bot'en vil selvfølgelig ikke svare.

Lad os tjekke, om bot'en er oprettet – vi åbner.

api.telegram.org\/bot1234544311:AbcDefNNNNNNNNNNNNN\/getMe
hvor 1234544311:AbcDefNNNNNNNNNNNNN er den tidligere modtagne nøgle,
og vi får en streng af formen
{“ok”:true,“result”:{“”}}

Vi har den første hemmelige sætning (token). Nu skal vi finde den anden hemmelige tal - ID'et på chatten med botten. Hver chat, gruppe osv. er unik og har sit eget nummer (nogle gange med et minus for åbne grupper). For at finde dette nummer skal vi anmode om adressen i browseren (det er faktisk ikke nødvendigt at bruge en browser, men det kan være en god start for at forstå det bedre) hvor 1234544311:NNNNNNNNN er dit token.

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

og få svar som

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

Vi har brug for именно chat_id.

Lad os tjekke, om vi kan skrive til chatten manuelt: vi kalder adressen fra browseren

https://api.telegram.org/botditotokenu/sendMessage?chat_id=123456789&text="Life is directed motion"

Hvis du har modtaget en besked fra botten i chatten - okay, så går du videre til næste trin.

Dermed (gennem browseren) kan du altid tjekke, hvor problemerne ligger - om det er i din linkgenerering, eller om noget er lukket af og ikke fungerer.

Hvad du skal vide, før du fortsætter med at læse

I Telegram er der flere typer af gruppechats (åbne, lukkede). For disse chats varierer nogle funktioner (f.eks. id), hvilket nogle gange kan skabe problemer.

Lad os antage, at det er slutningen af 2019, og selv helten i vores tid, den velkendte Menneske-Orkester (administrator, jurist, informationssikkerhedsspecialist, programmør og næsten MVP) Yevgeny V. kan skelne mellem variablen $i og en array, har lært om loops, og måske i de næste par år lærer Chocolatey, og så når vi til Parallel processing with PowerShell og ForEach-Object Parallel bliver det.

1. Vi tænker over, hvad vores bot skal gøre

Jeg havde ingen idéer, så jeg måtte tænke. Jeg har allerede skrevet en notesbog-bot. Jeg var ikke interesseret i at lave en bot 'der sender noget et eller andet sted'. For at tilslutte Azure har man brug for et kreditkort, og hvor får en skoleelev det fra? Det er værd at bemærke, at det ikke er så slemt: de største cloud-udbydere tilbyder en slags gratis prøveperiode (men man har stadig brug for et kreditkort - og det vil blive debiteret, tror jeg, en dollar. Jeg kan ikke huske, om det blev tilbagebetalt senere).

Uden AI ML er det ikke så interessant at lave en bot, der er en klodset digter.

Jeg besluttede at lave en bot, der vil minder mig (eller ikke mig) om engelske ord fra ordbogen.
Ordbogen, for ikke at bøvle med en database, vil ligge i en tekstfil og blive opdateret manuelt.
I dette tilfælde er målet at vise grundlaget for arbejdet, ikke at lave et halvgodt produkt.

2. Prøver hvad og hvordan første gang

Opret en mappe C:poshtranslate
Lad os først se, hvad vi har af PowerShell, ved at starte ISE via kør
powershell ise
eller finde PowerShell ISE i de installerede programmer.
Efter lanceringen åbnes en almindelig velkendt "nogen slags editor". Hvis tekstfeltet ikke vises, kan du altid klikke på "File - create new".

Lad os se versionen af PowerShell - skriv i tekstfeltet:

get-host 

og tryk på F5.

PowerShell vil spørge, om du vil gemme - "The script you are about to run will be saved.", lad os acceptere, og gemme filen fra PowerShell i C:poshtranslate med navnet myfirstbotBT100.

Efter lanceringen vil vi få en datatabel i det nederste tekstvindue:

Navn             : Windows PowerShell ISE Host
Version          : 5.1.(og så videre)

Jeg har 5.1 og noget, det er tilstrækkeligt. Hvis du har en gammel Windows 7/8, er det ikke noget problem - men PowerShell skal opdateres til version 5 - for eksempel ved vejledningen.

Skriv i kommandolinjen nedenfor Get-Date, tryk Enter, se på tiden, gå til rodmappen med kommandoen
cd
og ryd skærmen med kommandoen cls (nej, brug ikke rm)

Lad os nu tjekke, hvad og hvordan det fungerer - vi skriver ikke engang kode, men to linjer, og forsøger at forstå, hvad de gør. Vi kommenterer linjen med get-host med symbolet # og tilføjer lidt.

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

(Interessant nok. I dropdown-listen til kodestil på Habr er der et par dusin varianter - men PowerShell er ikke der. Dos er der. Perl er der.)

Og vi kører koden ved at trykke på F5 eller ">" fra GUI.

Vi får output:

Lørdag den 8. december 2019 21:00:50 PM (eller noget i den retning)

Lad os nu se på disse to linjer, og nogle interessante punkter, så vi ikke skal tilbage til dette senere.

I modsætning til Pascal (og ikke kun), forsøger PowerShell selv at bestemme, hvilken type der skal tildeles variablen. Mere om dette er beskrevet i artiklen Grundlæggende om typificering i programmeringssprog
Derfor, når vi opretter variablen $TimeNow og tildeler den den aktuelle dato og tid (Get-Date), behøver vi ikke bekymre os om, hvilken datatype der vil være.

Sandt nok kan det være smertefuldt at være uvidende om dette senere, men det er senere. Der vil være et eksempel i teksten nedenfor.
Lad os se, hvad vi har fået. Udfør (i kommandolinjen)

$TimeNow | Get-member

og vi får en side med uforståelig tekst

Eksempel på uforståelig tekst nummer 1

PS C:&gt; $TidNu | Get-member
   TypeName: System.DateTime
Navn                 Medlemstype     Definition                                                                                                                                       
----                 ----------     ----------                                                                                                                                       
Tilføj                  <b>Metode         </b>datetime Tilføj(timespan værdi)  
..
Visningshint          NoteProperty   VisningshintType Visningshint=DateTime                                                                                                             
Dato                 <b>Egenskab       </b>datetime Dato {get;}                                                                                                                             
År                 Egenskab       int År {get;}   
..                                                                                                                               
DateTime             ScriptProperty System.Object DateTime {get=if ((&amp; { Set-StrictMode -Version 1; $this.Visningshint }) -ieq  "Dato")...                                         

Som det ses, er der blevet oprettet en variabel af typen TypeName: System.DateTime med en masse metoder (med hensyn til hvad vi kan gøre med denne objekts variabel) og egenskaber.

Lad os kalde $TimeNow.DayOfYear — vi får dagenummeret på året.
Lad os kalde $TimeNow.DayOfYear | Get-Member — vi får TypeName: System.Int32 og gruppen af metoder.
Lad os kalde $TimeNow.ToUniversalTime() — og vi får tiden i UTC

er oversat

Nogle gange er det nødvendigt at køre et program op til en bestemt linje og se tilstanden på programmet på det tidspunkt. Til dette er der en Debug-funktion i ISE — toggle break point.
Sæt et breakpoint et sted i midten, kør disse to linjer, og se, hvordan stoppet ser ud.

3. Forståelse af interaktion med Telegram-botten

Selvfølgelig er der skrevet meget mere om interaktionen med botten, om alle getpush og så videre, men teori kan overvejes fakultativt.

I vores tilfælde er det nødvendigt:

  • At lære at sende noget i beskeden
  • At lære at modtage noget fra beskeden

3.1 Lære at sende noget i beskeden og modtage fra den

Lidt kode — del 3

Write-output "Dette er del 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 = "Livet er rettet bevægelse - " + $TimeNow

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

Invoke-WebRequest -Uri $URL4SEND

og i RF får vi på dette sted fejlen Unable to connect to the remote server.

Eller måske ikke — afhænger af teleoperatøren og om proxyen er konfigureret og fungerer.
Nå, vi må tilføje en proxy. Husk — brugen af ukrypteret og overhovedet ikke legitim proxy er ekstremt farlig for dit helbred.

Opgaven med at finde en fungerende proxy er ikke særligt svær — de fleste offentliggjorte http-proxyer fungerer. Jeg fik det til at fungere ved den femte i rækken.

Syntaksen for at bruge en proxy:

Invoke-WebRequest -Uri $URL4SEND -Proxy $MyProxy

Hvis du har modtaget en besked i din chat med botten — så er alt godt, vi kan gå videre. Hvis ikke — fortsæt fejlfinding.

Du kan se, hvordan din streng $URL4SEND bliver til, og prøve at anmode om den i browseren, for eksempel sådan her:

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

3.2. Vi har lært at skrive "noget" i chatten, nu vil vi prøve at læse

Lad os tilføje yderligere 4 linjer og se, hvad der er indeni gennem | 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

Det mest interessante præsenterer os med

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

Lad os se, hvad der er i dem:

Write-Host "ParsedHtml"
$MyMessageGet.ParsedHtml # her er noget interessant
Write-Host "RawContent"
$MyMessageGet.RawContent # og her er også noget interessant, men samtidig også læsbart.
Write-Host "Content"
$MyMessageGet.Content

Hvis alt fungerer, vil du få en lang streng som denne:

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

Desværre, i den tidligere udgivne artikel om Telegram-bot til systemadministratorer blev denne linje (ja, ifølge $MyMessageGet.RawContent | get-member — det er System.String), allerede blevet gennemgået.

4. Behandle det modtagne (vi kan allerede sende noget)

Som nævnt før her, ligger det vigtigste i content. Lad os se nærmere på det.

Først vil vi skrive et par sætninger til botten fra webgrænsefladen eller telefonen

/message1
/message2
/message3

og se gennem browseren på den adresse, der blev dannet i variablen $URLGET.

Vi vil se noget som:

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

Hvad er dette? En kompleks objektstruktur med arrays af objekter, der indeholder en gennemgående identifikator for beskeden, chat-id, afsender-id og en masse information.

Men vi behøver ikke at analysere „hvad er dette for en objekt“ — en del af arbejdet er allerede udført for os. Lad os se, hvad der er indeni:

Læs de modtagne beskeder eller del 4

Write-Host "This is part 4" <# naturligvis er denne linje ikke nødvendig i den endelige tekst, men den er praktisk at søge efter. #> 

$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. Hvad skal vi nu gøre med dette

Vi gemmer den modtagne fil som myfirstbotBT105 eller hvad du foretrækker, ændrer overskriften og kommenterer hele den allerede skrevne kode ud gennem

<#start comment 105 end comment 105#>

Nu skal vi finde ud af, hvor vi kan få en ordbog (også hvordan — fra disken i en fil) og hvordan den vil se ud.

Selvfølgelig kan man fylde en kæmpe ordbog direkte ind i scripts teksten, men det er jo ikke hensigtsmæssigt.
Så lad os se på, hvad PowerShell kan arbejde med som standard.
Generelt set er det ligegyldigt, hvilken fil det arbejder med, men det er ikke ligegyldigt for os.
Vi har følgende valg: txt (kan, men hvorfor), csv, xml.
Eller vi kan se på allesammen. Lad os tage et kig på dem alle.
Vi opretter klassen MyVocabClassExample1 og variablen $MyVocabExample1
jeg bemærker, at klassen skrives uden $

lidt kode #5

write-host "Dette er del 5"
class MyVocabClassExample1 {
    [string]$Original  # ord
    [string]$Transcript
    [string]$Translate
    [string]$Example
    [int]$VocWordID # en meget interessant pointe. Brug af int med sine begrænsninger kan nogle gange føre til vilde konsekvenser, for eksempel den nylige sag med SSD HPE. I starten tilføjede jeg ikke dette element, men tilføjede det senere og kommenterede.
    }

$MyVocabExample1 = [MyVocabClassExample1]::new()
$MyVocabExample1.Original = "Apple"
$MyVocabExample1.Transcript = "[ ˈapəl ]"
$MyVocabExample1.Translate = "Æble"
$MyVocabExample1.Example = "Et æble er en sød, spiselig frugt, der produceres af et æbletræ (Malus domestica)"
# $MyVocabExample1.$VocWordID = 1

$MyVocabExample2 = [MyVocabClassExample1]::new()
$MyVocabExample2.Original = "Pear"
$MyVocabExample2.Transcript = "[ pe(ə)r ]"
$MyVocabExample2.Translate = "Pære"
$MyVocabExample2.Example = "Pæretræet (ˈpɛər) og busken er en art af slægten Pyrus"
# $MyVocabExample1.$VocWordID = 2

Lad os prøve at skrive dette i filer efter skabelonen.

Lidt kode #5.1

Write-Host $ScriptDir # jeg håber, at du ikke har kommenteret $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

— og vil få en fejl på linje Out-File -FilePath $MyFilenameExample01 -InputObject -Append $MyVocabExample2.

Vil ikke tilføje, åh åh hvilken irritation.

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

Lad os se, hvad der kom ud. Vidunderligt tekstformat — men hvordan eksportere det tilbage? Skal vi indtaste nogle tekstseparatorer, for eksempel kommaer?

Og i sidste ende få "fil med separatorer — kommaer, comma-separated values (CSV) A STOP VENT LIDT.
#

$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 

Det er let at se, at MS ikke adskiller sig meget i logikken; til en lignende procedure bruges -FilePath i ét tilfælde, -Path i et andet.

Derudover forsvandt det russiske sprog i den tredje fil, og i den fjerde fil kom der… nå, noget kom der. #TYPE System.Object[] 00
# „Count“,»Length»,«LongLength»,«Rank»,«SyncRoot»,«IsReadOnly»,«IsFixedSize»,«IsSynchronized»
#
Lad os omskrive lidt:

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

Det ser ud til at have hjulpet — men formatet tilfredsstiller mig stadig ikke.

Især kan jeg ikke lide, at jeg ikke kan lægge strenge fra objektet direkte i en fil.
Forresten, siden vi begynte å skrive til filer - burde vi kanskje begynne å føre en oppstartlogg? Vi har tid som en variabel, og vi kan angi filnavn.

Det er ikke så mye å skrive ennå, men vi kan tenke på hvordan vi best kan håndtere loggrotasjon.
La oss prøve xml.

Litt 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

Eksport til xml har mange fordeler - lesbarhet, eksport av hele objektet, og ingen behov for å utføre oppappend.

La oss prøve å lese xml-fil.

Litt lesing fra xml

$MyFilenameExample06 = $ScriptDir + "Example06.xml"
$MyVocabExample4AsArray = Import-Clixml -Path $MyFilenameExample06
# $MyVocabExample4AsArray 
# $MyVocabExample4AsArray[0]
# og litt om de helt uventede nyansene. Powershell oppfører seg av og til ikke slik man skulle forvente.
# for eksempel, disse to utskriftene mine er ulike
# Write-Output $MyVocabExample4AsArray 
# write-host $MyVocabExample4AsArray 

La oss gå tilbake til oppgaven. Vi har skrevet en prøvefil, lest den, lagringsformatet er klart, og ved behov kan vi lage en liten tekstbehandler for å legge til og fjerne linjer.

Jeg minner om at oppgaven var å lage en liten læringsbot.

Arbeidsformat: jeg sender boten kommandoen «eksempel», boten sender meg et tilfeldig valgt ord og transkripsjon, og etter 10 sekunder sender den oversettelsen og kommentaren. Vi kan lese kommandoene, og vi skulle selvfølgelig gjerne lære å velge og sjekke proxy automatisk, og tilbakestille meldingstellere til null.

Vi fjerner kommentarene fra alt tidligere kommentert som unødvendig, kommenterer de nå unødvendige eksemplene med txt og csv, og lagrer filen som versjon B106.

Å, ja. Vi sender noe til boten en gang til.

6. Sending fra funksjoner og mer

Før vi behandler mottak, må vi lage en funksjon for å sende «noe», annet enn testmeldingen.

Selvfølgelig, i eksemplet vårt vil det være bare en sending fra én behandling, men hva om vi må gjøre det flere ganger?

Det er enklere å skrive en funksjon. Så, vi har en objektvariabel $MyVocabExample4AsArray, lest fra fil, som et array med to elementer.
La oss begynne å lese.

Samtidig skal vi se på klokken, vi vil trenge det senere (egentlig i dette eksemplet - trenge det ikke 🙂

Litt kode #6.1

Write-Output "Dette er Del 6"
$Timezone = (Get-TimeZone)
IF($Timezone.SupportsDaylightSavingTime -eq $True){
    $TimeAdjust =  ($Timezone.BaseUtcOffset.TotalSeconds + 3600) } # justeret tid
    ELSE{$TimeAdjust = ($Timezone.BaseUtcOffset.TotalSeconds) 
    }
    
function MyFirstFunction($SomeExampleForFunction1){
$TimeNow = Get-Date
$TimeNow.ToUniversalTime()
# $MyText02 = $TimeNow + " " + $SomeExampleForFunction1 # og her får vi en fejl
$MyText02 = $SomeExampleForFunction1 + " " + $TimeNow # men her får vi ikke, den der gætter hvorfor, er dygtig.

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

Det er nemt at se, at funktionen kalder $MyToken og $MyChatID, som er defineret tidligere.

Det må man ikke gøre, og hvis $MyToken er den samme for hver bot, så vil $MyChatID ændre sig afhængigt af chatten.

Men da dette er et eksempel, vil vi ignorere det for nu.

Da $MyVocabExample4AsArray ikke er et array, selvom det ligner et, så kan man ikke bare tage og anmode om dets længde.

Vi bliver endnu en gang nødt til at gøre noget, vi ikke bør — bryde reglerne og tage og tælle

Lidt kode #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)
# eller på én linje
# MyFirstFunction($MyVocabExample4AsArray[Get-Random -Minimum 0 -Maximum ($MaxRandomExample -1)].Example)
# Gæt selv, hvilket eksempel der er lettere at læse for udenforstående.

Tilfældig interessant funktion. Antag vi vil have 0 eller 1 (vi har kun to elementer i arrayet). Hvis vi sætter grænserne til 0..1 — får vi så "1"?
nej — det får vi ikke, vi har specielt angivet eksempel 2: Få et tilfældigt heltal mellem 0 og 99 Get-Random -Maximum 100
Derfor skal vi for 0..1 angive størrelsen 0..2, hvor den maksimale nummer i elementet = 1.

7. Håndtering af modtagne beskeder og maksimal længde på køen

Hvor var vi stoppet? vi har den modtagne variabel $MyMessageGet
og den udtrukne $Content4Pars01, hvorfra vi er interesserede i array-elementerne Content4Pars01.result

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

Vi sender botten /message10, /message11, /message12, /word og endnu engang /word og /hej.
Lad os se hvad vi har modtaget:

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

Vi gennemgår alt modtaget og sender svar, hvis beskeden var /word
case of konstruktion, det som nogle beskriver som if-elseif, kaldes i powershell gennem switch. I koden nedenfor bruges nøglen -wildcard, hvilket er helt unødvendigt og endda skadelig.

Lidt kode #7.1

Write-Output "Dette er del 7"
Foreach ($Result in $Content4Pars01.result) # Ja, det kan gøres hurtigere 
 { 
    switch -wildcard ($Result.message.text) 
            {
            "\/word" {MyFirstFunction($TextForExample1)}
            }
}

Lad os køre scriptet et par gange. Vi får det samme ord to gange for hver forsøg, især hvis vi har lavet en fejl i implementeringen af random.

Men vent. Vi har ikke sendt \/word igen, hvordan kan beskeden så behandles igen?

Køen til at sende beskeder til botten har en begrænset længde (jeg mener, 100 eller 200 beskeder), og den skal renses manuelt.

I dokumentationen er dette selvfølgelig beskrevet, men den skal læses!

I dette tilfælde har vi brug for parameteren ?chat_id, og &timeout, &limit, &parse_mode=HTML samt &disable_web_page_preview=true er endnu ikke nødvendige.

Dokumentationen til telegram api findes her
På engelsk står der sort på hvidt:
Identifier for den første opdatering, der skal returneres. Skal være større med én end den højeste blandt identificerne for tidligere modtagne opdateringer. Som standard returneres opdateringer, der starter med de tidligste
ukonfirmeret opdatering. En opdatering betragtes som bekræftet, så snart getUpdates kaldes med en offset højere end dens update_id. Den negative offset kan specificeres for at hente opdateringer, der starter fra -offset opdatering fra slutningen af opdateringskøen. Alle tidligere opdateringer vil blive glemt.

Lad os se på:

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

Lad os også nulstille — vi omskriver funktionen lidt. Vi har to muligheder — at overføre hele beskeden til funktionen og behandle den i sin helhed i funktionen, eller kun at give ID'en for beskeden og også nulstille den. Det andet virker lettere som eksempel.

Tidligere så vores forespørgsel "alle beskeder" sådan ud

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

og vil se sådan ud som

$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 

Ingen forhindrer dig i først at hente alle beskeder, behandle dem, og kun efter en succesfuld behandling anmode om unconfirmed -> confirmed.

Hvorfor giver det mening at bekræfte efter afslutningen af alle behandlinger? Det kan ske en fejl midt i eksekveringen, og hvis for eksempel en gratis chatbot springer over en enkelt besked, er det ikke så slemt, men hvis du behandler nogens løn eller en transaktion med kort, kan resultatet være værre.

Yderligere et par linjer kode

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

8. I stedet for konklusion

De vigtigste funktioner - læse meddelelser, nulstille køen, læse fra fil og skrive til fil er udført og vist.

Der er kun fire ting tilbage at gøre:

  • at sende det rigtige svar på anmodningen til chatten
  • at sende svaret til EN HVER chat, som botten er tilføjet til
  • at udføre koden i en løkke
  • at starte botten fra Windows-opgaveplanlæggeren.

Alle disse opgaver er enkle og lette at implementere ved at læse dokumentationen om parametre som
Set-ExecutionPolicy Unrestricted og -ExecutionPolicy Bypass
en løkke af typen

$TimeToSleep = 3 # polling hver 3 sekund
$TimeToWork = 10 # minutter
$HowManyTimes = $TimeToWork*60/$TimeToSleep # tæller for løkken
$MainCounter = 0
for ($MainCounter=0; $MainCounter -le $HowManyTimes) {
sleep $TimeToSleep
$MainCounter ++

Tak til alle, der læste færdig.

Kilde: habr.com

Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere 🔥 Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere | ProHoster