De sjabloon van de eenvoudigste telegrambot voor schoolkinderen in groep 7-9 op Powershell

Tijdens gesprekken met een vriend hoorde ik plotseling dat kinderen in groep 8 tot en met 10 op hun school helemaal geen programmeerles krijgen. Word, Excel en alles. Geen logo, zelfs Pascal niet, zelfs geen VBA voor Excel.

Ik was zeer verrast, opende het internet en begon te lezen -
Een van de taken van een gespecialiseerde school is het bevorderen van de opleiding van een nieuwe generatie die qua ontwikkeling en levensstijl voldoet aan de voorwaarden van de informatiemaatschappij.
Met deze cursus kunnen studenten hun kennis van de basisconstructies van de programmeertaal Pascal in de praktijk consolideren. (uit het programma van een gymzaal voor 2017)

Uiteindelijk besloot ik een paar uur te besteden aan het schetsen van een voorbeeld van ‘hoe je een eenvoudige bot voor schoolkinderen maakt’.

Hieronder ziet u hoe u nog een eenvoudige bot in Powershell kunt schrijven en deze kunt laten werken zonder een webhook, witte IP's, speciale servers, geïmplementeerde virtuele machines in de cloud, enzovoort - op een gewone thuis-pc met normaal Windows.

TLDR: Weer een saai artikel met grammaticale en feitelijke fouten, niets te lezen, geen humor, geen afbeeldingen.

Er staat niets nieuws in het artikel, vrijwel alles wat eerder geschreven is, heeft al op Habré gestaan, bijvoorbeeld in artikelen Instructies: Bots maken in Telegram и Telegram-bot voor systeembeheerder.
Bovendien is het artikel bewust overbodig gemaakt om niet telkens naar onderwijsliteratuur te verwijzen. Er zijn geen verwijzingen naar Gang 4, PowerShell Deep Dives of bijvoorbeeld de 5 pijlers van het AWS Well-Architected Framework in de tekst.

In plaats van een voorwoord kunt u dit overslaan

Sla gerust overIn 2006 bracht Microsoft PowerShell 1.0 uit voor het toenmalige Windows XP, Vista en Server 2003. In sommige opzichten verving het zaken als cmdbat-scripts, vb-scripts, Windows Script Host en JScript.

Zelfs nu nog kan PowerShell alleen worden beschouwd als de volgende stap na de Logo-opties, in plaats van het waarschijnlijk nog gebruikte Delphi (of iets ouder), ondanks de aanwezigheid van loops, klassen, functies, MS GUI-aanroepen, Git-integratie enzovoort.

Powershell wordt relatief zelden gebruikt; je kunt het alleen tegenkomen in de vorm van PowerShell Core, VMware vSphere PowerCLI, Azure PowerShell, MS Exchange, Desired State Configuration, PowerShell-webtoegang en een tiental zelden gebruikte programma's en functies. Misschien krijgt hij met de release een tweede adem WSL2, maar dat is het niet precies.

Powershell heeft daarnaast drie grote voordelen:

  1. Het is relatief eenvoudig, er is veel literatuur en voorbeelden over, en zelfs in het Russisch bijvoorbeeld een artikel over Foreach - uit het boek PowerShell diepgaand - over het verschil () en {}
  2. Hij gaat mee met de redacteur ISE, meegeleverd met Windows. Er is zelfs een soort debugger aanwezig.
  3. Vanuit daar kunt u gemakkelijk bellen componenten voor het bouwen van een grafische interface.

0. Voorbereiding.

We hebben nodig:

  • Windows-pc (ik heb Windows 10)
  • Tenminste een soort internettoegang (via NAT bijvoorbeeld)
  • Voor degenen die beperkte toegang hebben tot Telegram: freegate in de browser geïnstalleerd en geconfigureerd, in sommige moeilijke gevallen, samen met Symple DNS Crypt
  • Een werkende telegramclient op uw telefoon hebben
  • De basisprincipes begrijpen: wat een variabele, array of lus is.

Artikelen geopend en gelezen - Instructies: Bots maken in Telegram и Telegram-bot voor systeembeheerder

1. Laten we nog een testbot maken.

Omdat iedereen dit al weet en al is gebeurd, kun je het ook overslaanZoals vermeld in het bovenstaande artikel - Allereerst een bot voor Telegram - het is nog steeds een applicatie die aan jouw kant draait en verzoeken doet aan de Telegram Bot API. Bovendien is de API duidelijk: de bot heeft toegang tot een specifieke URL met parameters en Telegram reageert met een JSON-object.

Gerelateerde problemen: als u op een onbekende manier code uit een JSON-object haalt en deze op de een of andere manier ter uitvoering verzendt (niet met opzet), wordt de code voor u uitgevoerd.

Het creatieproces wordt beschreven in twee artikelen hierboven, maar ik herhaal: in een telegram openen we contacten, zoeken we naar @botfather, vertellen hem /newbot, maken een bot Botfortest12344321, noemen deze Mynext1234bot en ontvangen een bericht met een unieke sleutel van de formulier 1234544311:AbcDefNNNNNNNNNNNNNN

Zorg goed voor de sleutel en geef hem niet weg!

Vervolgens kun je de bot configureren, bijvoorbeeld het toevoegen aan groepen verbieden, maar in de eerste stappen is dit niet nodig.

Laten we BotFather om “/mybot” vragen en de instellingen aanpassen als we iets niet leuk vinden.

Laten we de contacten opnieuw openen, @Botfortest12344321 daar vinden (het is verplicht om de zoekopdracht met @ te starten), op “start” te klikken en naar de bot te schrijven “/Glory to the robots.” Het teken / is vereist, aanhalingstekens zijn niet nodig.
De bot zal natuurlijk niets antwoorden.

Laten we controleren of de bot is gemaakt en deze openen.

api.telegram.org/bot1234544311:AbcDefNNNNNNNNNNNNNN/getMe
waarbij 1234544311:AbcDefNNNNNNNNNNNNNN de eerder ontvangen sleutel is,
en krijg een lijn als
{"ok":true,"resultaat":{""}}

We hebben de eerste geheime zin (token). Nu moeten we het tweede geheime nummer achterhalen: de ID van de chat met de bot. Elke chat, groep, etc. is individueel en heeft zijn eigen nummer (soms met een minteken - voor open groepen). Om dit nummer te achterhalen, moeten we in de browser (in feite is dit helemaal niet nodig in de browser, maar voor een beter begrip kunt u ermee beginnen) het adres opvragen (waarbij 1234544311:NNNNNNNNNN uw token is

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

en krijg een reactie als

{"ok":true,"result":[{"update_id":...,... de chat":{"ID kaart":123456789

We hebben chat_id nodig.

Laten we controleren of we handmatig naar de chat kunnen schrijven: bel het adres vanuit de browser

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

Als je een bericht ontvangt van een bot in je chat, oké, je gaat door naar de volgende fase.

Zo kun je (via de browser) altijd controleren of er problemen zijn met het genereren van de link, of dat er ergens iets verborgen zit en niet werkt.

Wat u moet weten voordat u verder leest

Telegram heeft verschillende soorten groepschats (open, gesloten). Voor deze chats zijn sommige functies (bijvoorbeeld id) anders, wat soms voor problemen zorgt.

Laten we aannemen dat het eind 2019 is, en zelfs de held van onze tijd, het bekende Man-Orchestra (administrateur, advocaat, informatiebeveiligingsspecialist, programmeur en praktisch MVP) Evgeniy V. onderscheidt de $i-variabele van een array, heeft loops onder de knie, kijk in de komende paar jaar zal Chocolatey onder de knie krijgen, en dan Parallelle verwerking met PowerShell и ForEach-Object Parallel het zal komen.

1. We denken na over wat onze bot gaat doen

Ik had geen idee, ik moest nadenken. Ik heb al een bot-notebook geschreven. Ik wilde geen bot maken ‘die ergens heen stuurt’. Om verbinding te maken met Azure heb je een creditcard nodig, maar waar haalt de student deze vandaan? Opgemerkt moet worden dat alles niet zo erg is: de hoofdwolken geven gratis een soort testperiode (maar je hebt nog steeds een creditcardnummer nodig - en het lijkt alsof er een dollar van wordt afgeschreven. Ik weet niet meer of het werd later teruggestuurd.)

Zonder AI ML is het niet zo interessant om een ​​botarme dichter-wever te maken.

Ik besloot een bot te maken die mij (of niet mij) doet denken aan Engelse woorden uit het woordenboek.
Om geknoei met de database te voorkomen, wordt het woordenboek opgeslagen in een tekstbestand en handmatig bijgewerkt.
In dit geval is het de taak om de basisprincipes van het werk te laten zien, en niet om op zijn minst een gedeeltelijk voltooid product te maken.

2. Voor het eerst proberen wat en hoe

Laten we een map C:poshtranslate maken
Laten we eerst eens kijken wat voor soort powershell we hebben, laten we ISE lanceren via start-run
powershell ise
of zoek Powershell ISE in geïnstalleerde programma's.
Na het starten wordt de gebruikelijke bekende "een soort editor" geopend; als er geen tekstveld is, kunt u altijd op "Bestand - nieuwe maken" klikken.

Laten we eens kijken naar de versie van powershell - schrijf in het tekstveld:

get-host 

en druk op F5.

Powershell zal aanbieden om op te slaan - "Het script dat u gaat uitvoeren zal worden opgeslagen.", wij zijn het daarmee eens, en slaan het bestand op vanuit powershell met de naam in C: poshtranslate myfirstbotBT100.

Na de lancering krijgen we in het onderste tekstvenster een gegevenstabel:

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

Ik heb iets 5.1, dat is genoeg. Als je een oude Windows 7/8 hebt, is dat geen probleem - hoewel PowerShell wel moet worden bijgewerkt naar versie 5 - b.v. instructies.

Typ Get-Date in de onderstaande opdrachtregel, druk op Enter, kijk naar de tijd en ga met de opdracht naar de hoofdmap
cd
en maak het scherm leeg met het cls-commando (nee, je hoeft rm niet te gebruiken)

Laten we nu eens kijken wat werkt en hoe - laten we niet eens de code schrijven, maar twee regels, en proberen te begrijpen wat ze doen. Laten we de regel met get-host becommentariëren met het #-symbool en er een beetje aan toevoegen.

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

(Wat interessant is, is dat er in de vervolgkeuzelijst voor codeopmaak op Habré twintig opties zijn, maar Powershell is er niet. Dos is er. Perl is er.)

En laten we de code uitvoeren door op F5 of ">" te drukken vanuit de GUI.

We krijgen de volgende uitvoer:

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

Laten we nu eens naar deze twee regels en enkele interessante punten kijken, zodat we hier in de toekomst niet meer op terugkomen.

In tegenstelling tot Pascal (en niet alleen) probeert PowerShell zelf te bepalen welk type aan een variabele moet worden toegewezen; meer details hierover zijn geschreven in het artikel Educatief programma over typen in programmeertalen
Door een $TimeNow-variabele te maken en deze de waarde van de huidige datum en tijd toe te wijzen (Get-Date), hoeven we ons dus niet al te veel zorgen te maken over welk type gegevens daar zullen zijn.

Het is waar dat deze onwetendheid later pijn kan doen, maar dat is voor later. Hieronder in de tekst staat een voorbeeld.
Laten we eens kijken wat we hebben. Laten we uitvoeren (op de opdrachtregel)

$TimeNow | Get-member

en krijg een pagina met onbegrijpelijke tekst

Voorbeeld van onbegrijpelijke tekst nummer 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")...                                         

Zoals u kunt zien, is er een variabele van het type TypeName: System.DateTime gemaakt met een aantal methoden (in de zin van wat we met dit variabele object kunnen doen) en eigenschappen.

Laten we bellen $TimeNow.DayOfYear — we krijgen het nummer van de dag van het jaar.
Laten we bellen $TimeNow.DayOfYear | Get-Member - krijgen TypeName: System.Int32 en een groep methoden.
Laten we bellen $TimeNow.ToUniversalTime() - en krijg de tijd in UTC

Debugger

Soms komt het voor dat het nodig is om een ​​programma tot een bepaalde regel uit te voeren en de status van het programma op dat moment te bekijken. Voor dit doel heeft ISE een Debug-functie - toggle break point
Plaats ergens in het midden een breekpunt, voer deze twee lijnen uit en kijk hoe de pauze eruit ziet.

3. De interactie met de Telegram-bot begrijpen

Natuurlijk is er nog meer literatuur geschreven over de interactie met de bot, met alle getpush enzovoort, maar de kwestie van de theorie kan optioneel worden overwogen.

In ons geval is het noodzakelijk:

  • Leer iets in correspondentie te versturen
  • Leer iets uit correspondentie te halen

3.1 Leren iets in correspondentie te versturen en daarvan te ontvangen

Een kleine code - deel 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

en in de Russische Federatie krijgen we op dit punt de foutmelding Kan geen verbinding maken met de externe server.

Of we ontvangen het niet - hangt af van de telecomoperator en of de proxy is geconfigureerd en werkt
Het enige dat overblijft is het toevoegen van een proxy. Houd er rekening mee dat het gebruik van een niet-versleutelde en doorgaans frauduleuze proxy uiterst gevaarlijk is voor uw gezondheid.

De taak om een ​​werkende proxy te vinden is niet erg moeilijk: de meeste gepubliceerde http-proxy's werken. Ik denk dat de vijfde voor mij werkte.

Syntaxis met proxy:

Invoke-WebRequest -Uri $URL4SEND -Proxy $MyProxy

Als je een bericht ontvangt in je chat met een bot, dan is alles in orde, je kunt verder. Als dit niet het geval is, gaat u verder met debuggen.

U kunt zien waar uw tekenreeks $URL4SEND in verandert en deze als volgt in de browser opvragen:

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

3.2. We hebben geleerd hoe we 'iets' in de chat kunnen schrijven, laten we nu proberen het te lezen

Laten we nog 4 regels toevoegen en kijken wat er in zit via | word lid

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

Het meest interessante wordt ons aangereikt

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

Laten we eens kijken wat erin zit:

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

Als alles voor u werkt, krijgt u een lange rij zoals:

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

Gelukkig staat in het eerder gepubliceerde artikel Telegram bot voor systeembeheerder deze regel (ja, volgens $MyMessageGet.RawContent | get-member is System.String), is al gedemonteerd.

4. Verwerken wat je ontvangt (wij weten al hoe we iets moeten versturen)

Zoals al geschreven hier, de meest noodzakelijke dingen liggen in de inhoud. Laten we het eens nader bekijken.

Eerst schrijven we nog een paar zinnen naar de bot vanuit de webinterface of vanaf de telefoon

/message1
/message2
/message3

en kijk via de browser naar het adres dat is gevormd in de variabele $URLGET.

We zullen zoiets zien als:

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

Wat het is? Een complex object uit reeksen objecten die een end-to-end bericht-ID, chat-ID, verzend-ID en een heleboel andere informatie bevatten.

We hoeven echter niet uit te zoeken “wat voor soort object dit is” - een deel van het werk is al voor ons gedaan. Laten we eens kijken wat erin zit:

Ontvangen berichten lezen of deel 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. Wat moeten we er nu aan doen?

Laten we het resulterende bestand opslaan onder de naam myfirstbotBT105 of wat u maar wilt, de titel wijzigen en alle reeds geschreven code becommentariëren via

<#start comment 105 end comment 105#>

Nu moeten we beslissen waar we het woordenboek willen krijgen (nou ja, waar - op schijf in een bestand) en hoe het eruit zal zien.

Je kunt natuurlijk een enorm woordenboek rechtstreeks in de tekst van het script schrijven, maar dit doet er helemaal niet toe.
Laten we dus eens kijken waar Powershell normaal mee kan werken.
Over het algemeen maakt het hem niet uit met welk bestand hij moet werken, voor ons maakt het niet uit.
We hebben een keuze: txt (dat kan, maar waarom), csv, xml.
Kunnen we iedereen bekijken? Laten we iedereen zien.
Laten we een klasse MyVocabClassExample1 en een variabele $MyVocabExample1 maken
Ik merk op dat de klasse is geschreven zonder $

een code #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

Laten we proberen dit in bestanden te schrijven met behulp van voorbeeldig.

Sommige code #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

- en we krijgen een foutmelding op de regel Out-File -FilePath $MyFilenameExample01 -InputObject -Append $MyVocabExample2.

Hij wil er niet aan toevoegen: ah-ah, wat jammer.

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

Laten we afwachten wat er gebeurt. Geweldige tekstweergave - maar hoe exporteer je deze terug? Moet ik een soort tekstscheidingstekens introduceren, zoals komma's?

En uiteindelijk krijg je een “door komma’s gescheiden waarden (CSV) bestand A STOP WACHT.
#

$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 

Zoals gemakkelijk te zien is, onderscheidt MS zich niet bijzonder door zijn logica; voor een vergelijkbare procedure wordt in het ene geval -FilePath gebruikt, in een ander geval -Path.

Bovendien verdween in het derde bestand de Russische taal, in het vierde bestand bleek... nou ja, er gebeurde iets. #TYPE Systeem.Object[] 00
# "Aantal", "Lengte", "Lange lengte", "Rang", "SyncRoot", "Is alleen-lezen", "Is vast formaat", "Is gesynchroniseerd"
#
Laten we het een beetje herschrijven:

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

Het lijkt te hebben geholpen, maar ik vind het formaat nog steeds niet leuk.

Ik vind het vooral niet leuk dat ik regels van een object niet rechtstreeks in een bestand kan plaatsen.
Kunnen we trouwens een opstartlogboek bijhouden sinds we naar bestanden zijn gaan schrijven? We hebben tijd als variabele, we kunnen de bestandsnaam instellen.

Toegegeven, er valt nog niets te schrijven, maar je kunt wel nadenken over hoe je de logboeken het beste kunt roteren.
Laten we XML voorlopig proberen.

Sommige xml-bestanden

$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

Exporteren naar XML heeft veel voordelen: leesbaarheid, export van het hele object en geen noodzaak om een ​​uppend uit te voeren.

Laten we het proberen xml-bestand lezen.

Een beetje lezen uit xml

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

Laten we terugkeren naar de taak. We hebben een testbestand geschreven, gelezen, het opslagformaat is duidelijk, indien nodig kun je een aparte kleine bestandseditor schrijven om regels toe te voegen en te verwijderen.

Laat me je eraan herinneren dat het de taak was om een ​​kleine trainingsbot te maken.

Werkformaat: ik stuur het commando “voorbeeld” naar de bot, de bot stuurt me een willekeurig geselecteerd woord en transcriptie en stuurt me na 10 seconden een vertaling en commentaar. We weten hoe we commando's moeten lezen, we zouden ook graag willen leren hoe we automatisch proxy's kunnen selecteren en controleren, en hoe we berichtentellers naar de vergetelheid kunnen resetten.

Laten we alles wat eerder is becommentarieerd als onnodig verwijderen, de nu onnodige voorbeelden van commentaar voorzien met txt en csv, en het bestand opslaan als versie B106

Oh ja. Laten we opnieuw iets naar de bot sturen.

6. Verzending vanuit functies en meer

Voordat u de ontvangst verwerkt, moet u een functie creëren voor het verzenden van “tenminste iets” anders dan een testbericht.

Natuurlijk hebben we in het voorbeeld slechts één verzending en slechts één verwerking, maar wat als we hetzelfde meerdere keren moeten doen?

Het is gemakkelijker om een ​​functie te schrijven. We hebben dus een variabele van het type object $MyVocabExample4AsArray, gelezen uit het bestand, in de vorm van een array van maar liefst twee elementen.
Laten we gaan lezen.

Tegelijkertijd zullen we met de klok omgaan; we zullen hem later nodig hebben (in dit voorbeeld hebben we hem zelfs niet nodig :)

Sommige code #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
}

Zoals u gemakkelijk kunt zien, roept de functie $MyToken en $MyChatID aan, die eerder hardgecodeerd waren.

Het is niet nodig om dit te doen, en als $MyToken er één is voor elke bot, zal $MyChatID veranderen afhankelijk van de chat.

Omdat dit echter een voorbeeld is, laten we het voorlopig buiten beschouwing.

Omdat $MyVocabExample4AsArray geen array is, hoewel deze er wel erg op lijkt je kunt het niet zomaar aannemen vraag de lengte ervan aan.

Opnieuw zullen we iets moeten doen dat niet kan worden gedaan - parachutespringen niet volgens de code - het nemen en tellen

Sommige code #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 interessante functie. Laten we zeggen dat we 0 of 1 willen ontvangen (we hebben slechts twee elementen in de array). Als we de grenzen 0..1 stellen, krijgen we dan “1”?
nee - we snappen het niet, we hebben een speciaal voorbeeld Voorbeeld 2: Verkrijg een willekeurig geheel getal tussen 0 en 99 Get-Random -Maximum 100
Daarom moeten we voor 0..1 de grootte 0..2 instellen, met het maximale elementnummer = 1.

7. Verwerking van inkomende berichten en maximale wachtrijlengte

Waar zijn we eerder gestopt? we hebben de ontvangen variabele $MyMessageGet
en $Content4Pars01 verkregen daaruit, waarvan we geïnteresseerd zijn in de elementen van de Content4Pars01.result-array

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

Laten we de bot /message10, /message11, /message12, /word en nogmaals /word en /hello sturen.
Laten we eens kijken wat we hebben:

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

Laten we alles wat we hebben ontvangen doornemen en een reactie sturen als het bericht /woord was
het geval van construct, wat sommigen omschrijven als if-elseif, wordt in powershell genoemd via schakelaar. Tegelijkertijd gebruikt de onderstaande code de -wildcard-sleutel, wat volkomen onnodig en zelfs schadelijk is.

Sommige code #7.1

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

Laten we het script een paar keer uitvoeren. We krijgen voor elke uitvoeringspoging twee keer hetzelfde woord, vooral als we een fout hebben gemaakt bij de implementatie van willekeurig.

Maar hou op. We hebben /word niet opnieuw verzonden, dus waarom wordt het bericht opnieuw verwerkt?

De wachtrij voor het verzenden van berichten naar de bot heeft een eindige lengte (100 of 200 berichten, denk ik) en moet handmatig worden gewist.

Dit staat uiteraard beschreven in de documentatie, maar je moet het wel lezen!

In dit geval hebben we de parameter ?chat_id nodig en zijn &timeout, &limit, &parse_mode=HTML en &disable_web_page_preview=true nog niet nodig.

Documentatie voor Telegram-API is hier
Er staat in het wit en Engels:
Identificatie van de eerste update die moet worden geretourneerd. Moet één groter zijn dan de hoogste van de ID's van eerder ontvangen updates. Updates beginnen standaard met de vroegste
niet bevestigd update worden geretourneerd. Een update wordt als bevestigd beschouwd zodra getUpdates wordt aangeroepen met een compenseren hoger dan zijn update_id. De negatieve offset kan worden opgegeven om updates op te halen vanaf -offset update vanaf het einde van de updateswachtrij. Alle eerdere updates worden vergeten.

Laten we eens kijken naar:

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

Ja, en we zullen het resetten en de functie een beetje herschrijven. We hebben twee opties: geef het volledige bericht door aan de functie en verwerk het volledig in de functie, of geef alleen de bericht-ID op en reset het. De tweede ziet er bijvoorbeeld eenvoudiger uit.

Voorheen zag onze zoekopdrachtreeks 'alle berichten' er zo uit

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

en het zal er zo uitzien

$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 

Niemand verbiedt u om eerst alle berichten te ontvangen, te verwerken, en pas na succesvolle verwerking aanvraag onbevestigd -> bevestigd.

Waarom is het zinvol om een ​​bevestiging te vragen nadat alle verwerkingen zijn voltooid? Een mislukking is mogelijk tijdens de uitvoering, en als, voor het voorbeeld van een gratis chatbot, het missen van een enkel bericht niets bijzonders is, dan kan het resultaat slechter zijn als u iemands salaris of kaarttransactie verwerkt.

Nog een paar regels code

$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. In plaats van een conclusie

Basisfuncties - berichten lezen, wachtrij opnieuw instellen, lezen van bestand en schrijven naar bestand worden uitgevoerd en weergegeven.

Er zijn nog maar vier dingen te doen:

  • het juiste antwoord verzenden op een verzoek in de chat
  • een antwoord sturen op ELKE chat waaraan de bot is toegevoegd
  • code in een lus uitvoeren
  • een bot starten vanuit de Windows-planner.

Al deze taken zijn eenvoudig en kunnen gemakkelijk worden uitgevoerd door de documentatie over parameters zoals te lezen
Set-ExecutionPolicy Onbeperkt en -ExecutionPolicy Bypass
cyclus van het formulier

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

Bedankt aan iedereen die heeft gelezen.

Bron: www.habr.com

Voeg een reactie