Vorlage für einen einfachen Telegram-Bot für Schüler der Klassen 7-9 mit Powershell

Bei Gesprächen mit einem Freund erfuhr ich plötzlich, dass Kindern der Klassen 8 bis 10 an ihrer Schule überhaupt kein Programmierunterricht erteilt wird. Word, Excel und alles. Kein Logo, nicht einmal Pascal, nicht einmal VBA für Excel.

Ich war sehr überrascht, öffnete das Internet und begann zu lesen -
Zu den Aufgaben einer Fachschule gehört es, die Bildung einer neuen Generation zu fördern, die in ihrem Entwicklungsstand und Lebensstil den Bedingungen der Informationsgesellschaft entspricht.
Dieser Kurs ermöglicht es den Studierenden, ihr Wissen über die grundlegenden Konstrukte der Programmiersprache Pascal in der Praxis zu festigen. (aus dem Programm einiger Gymnasien für 2017)

Am Ende beschloss ich, ein paar Stunden damit zu verbringen, ein Beispiel dafür zu skizzieren, „wie man einen einfachen Bot für Schulkinder erstellt“.

Im Folgenden erfahren Sie, wie Sie einen weiteren einfachen Bot in Powershell schreiben und dafür sorgen, dass er ohne Webhook, weiße IPs, dedizierte Server, bereitgestellte virtuelle Maschinen in der Cloud usw. funktioniert – auf einem normalen Heim-PC mit normalem Windows.

TLDR: Ein weiterer langweiliger Artikel mit grammatikalischen und sachlichen Fehlern, nichts zum Lesen, kein Humor, keine Bilder.

Der Artikel enthält nichts Neues, fast alles, was zuvor geschrieben wurde, war bereits über Habré, beispielsweise in Artikeln Anleitung: So erstellen Sie Bots in Telegram и Telegram-Bot für Systemadministratoren.
Darüber hinaus ist der Artikel bewusst redundant gehalten, um nicht jedes Mal auf pädagogische Literatur zu verweisen. Im Text gibt es keine Hinweise auf Gang 4, PowerShell Deep Dives oder beispielsweise die 5 Säulen des AWS Well-Architected Framework.

Anstelle eines Vorworts können Sie es auch überspringen

Überspringen Sie es gerneIm Jahr 2006 veröffentlichte Microsoft PowerShell 1.0 für die damaligen Betriebssysteme Windows XP, Vista und Server 2003. In gewisser Weise ersetzte es Dinge wie Cmdbat-Skripte, VB-Skripte, Windows Script Host und JScript.

Selbst jetzt kann PowerShell nur als nächster Schritt nach den Logo-Optionen angesehen werden, anstelle des wahrscheinlich immer noch verwendeten Delphi (oder etwas Älteres), trotz des Vorhandenseins von Schleifen, Klassen, Funktionen, MS GUI-Aufrufen, Git-Integration und so weiter.

Powershell kommt relativ selten zum Einsatz; man trifft nur in Form von PowerShell Core, VMware vSphere PowerCLI, Azure PowerShell, MS Exchange, Desired State Configuration, PowerShell-Webzugriff und etwa ein Dutzend seltener genutzter Programme und Funktionen. Vielleicht bekommt er mit der Veröffentlichung neuen Wind WSL2, aber es ist nicht genau.

Powershell hat außerdem drei große Vorteile:

  1. Es ist relativ einfach, es gibt viel Literatur und Beispiele dazu und sogar auf Russisch, zum Beispiel einen Artikel über Foreach – aus dem Buch PowerShell im Detail - über den Unterschied () und {}
  2. Er geht mit dem Herausgeber ISE, in Windows enthalten. Es gibt dort sogar eine Art Debugger.
  3. Es ist einfach, von dort aus anzurufen Komponenten zum Aufbau einer grafischen Oberfläche.

0. Vorbereitung.

Wir brauchen:

  • Windows-PC (ich habe Windows 10)
  • Zumindest eine Art Internetzugang (z. B. über NAT)
  • Für diejenigen, die nur eingeschränkten Zugriff auf Telegram haben – Freegate im Browser installieren und konfigurieren, in einigen schwierigen Fällen zusammen mit Symple DNS Crypt
  • Sie haben einen funktionierenden Telegram-Client auf Ihrem Telefon
  • Die Grundlagen verstehen – was eine Variable, ein Array oder eine Schleife ist.

Geöffnete und gelesene Artikel - Anleitung: So erstellen Sie Bots in Telegram и Telegram-Bot für Systemadministratoren

1. Lassen Sie uns einen weiteren Testbot erstellen.

Da dies bereits jeder weiß und bereits passiert ist, können Sie es auch überspringenWie im obigen Artikel erwähnt – Zunächst einmal ein Bot für Telegram – Es handelt sich immer noch um eine Anwendung, die auf Ihrer Seite ausgeführt wird und Anfragen an die Telegram-Bot-API stellt. Darüber hinaus ist die API klar – der Bot greift mit Parametern auf eine bestimmte URL zu und Telegram antwortet mit einem JSON-Objekt.

Verwandte Probleme: Wenn Sie auf unbekannte Weise Code aus einem JSON-Objekt übernehmen und ihn irgendwie zur Ausführung senden (nicht absichtlich), wird der Code für Sie ausgeführt.

Der Erstellungsprozess wird oben in den beiden Artikeln beschrieben, aber ich wiederhole: In einem Telegramm öffnen wir Kontakte, suchen nach @botfather, teilen ihm /newbot mit, erstellen einen Bot Botfortest12344321, nennen ihn Mynext1234bot und erhalten eine Nachricht mit einem eindeutigen Schlüssel des Formular 1234544311:AbcDefNNNNNNNNNNNNNN

Passen Sie gut auf den Schlüssel auf und geben Sie ihn nicht weg!

Anschließend können Sie den Bot konfigurieren, beispielsweise das Hinzufügen zu Gruppen verbieten, in den ersten Schritten ist dies jedoch nicht erforderlich.

Fragen wir BotFather nach „/mybot“ und passen die Einstellungen an, wenn uns etwas nicht gefällt.

Öffnen wir die Kontakte erneut, suchen dort @Botfortest12344321 (die Suche muss unbedingt mit @ gestartet werden), klicken auf „Start“ und schreiben an den Bot „/Glory to the robots“. Das /-Zeichen ist erforderlich, Anführungszeichen sind nicht erforderlich.
Der Bot wird natürlich nichts antworten.

Überprüfen Sie, ob der Bot erstellt wurde, und öffnen Sie ihn.

api.telegram.org/bot1234544311:AbcDefNNNNNNNNNNNNNN/getMe
wobei 1234544311:AbcDefNNNNNNNNNNNNNN der zuvor empfangene Schlüssel ist,
und bekomme eine Zeichenfolge wie
{"ok":true,"result":{""}}

Wir haben die erste geheime Phrase (Token). Jetzt müssen wir die zweite Geheimnummer herausfinden – die ID des Chats mit dem Bot. Jeder Chat, jede Gruppe usw. ist individuell und hat eine eigene Nummer (manchmal mit einem Minus – für offene Gruppen). Um diese Nummer herauszufinden, müssen wir im Browser die Adresse (wobei 1234544311:NNNNNNNNNN Ihr Token ist) anfordern (tatsächlich ist dies im Browser überhaupt nicht erforderlich, aber zum besseren Verständnis können Sie damit beginnen).

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

und bekomme eine Antwort wie

{"ok":true,"result":[{"update_id":...,... Chat ":{"Ausweis":123456789

Wir brauchen chat_id.

Überprüfen wir, ob wir manuell in den Chat schreiben können: Rufen Sie die Adresse über den Browser auf

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

Wenn Sie in Ihrem Chat eine Nachricht von einem Bot erhalten, fahren Sie mit der nächsten Stufe fort.

So können Sie (über den Browser) jederzeit überprüfen, ob es Probleme bei der Linkgenerierung gibt, oder ob irgendwo etwas versteckt ist und nicht funktioniert.

Was Sie wissen müssen, bevor Sie weiterlesen

Telegram bietet verschiedene Arten von Gruppenchats (offen, geschlossen). Bei diesen Chats sind einige Funktionen (z. B. ID) unterschiedlich, was manchmal zu Problemen führt.

Nehmen wir an, es ist das Ende des Jahres 2019 und sogar der Held unserer Zeit, der bekannte Man-Orchestra (Administrator, Anwalt, Informationssicherheitsspezialist, Programmierer und praktisch MVP) Evgeniy V. unterscheidet die Variable $i aus einem Array, hat Loops gemeistert, schau dir die nächsten paar Jahre an, werde Chocolatey meistern, und dann Parallelverarbeitung mit PowerShell и ForEach-Object Parallel es wird kommen.

1. Wir überlegen, was unser Bot tun wird

Ich hatte keine Ideen, ich musste nachdenken. Ich habe bereits ein Bot-Notizbuch geschrieben. Ich wollte keinen Bot machen, „der etwas irgendwohin sendet“. Um eine Verbindung zu Azure herzustellen, benötigt man eine Kreditkarte, aber woher bekommt der Student diese? Es sei darauf hingewiesen, dass nicht alles so schlimm ist: Die Hauptwolken bieten eine Art Testzeitraum kostenlos an (aber Sie benötigen immer noch eine Kreditkartennummer - und es scheint, als würde ein Dollar davon abgebucht. Ich weiß nicht mehr, ob es wurde später zurückgegeben.)

Ohne KI ML ist es nicht so interessant, einen Bot-armen Dichter-Weber zu machen.

Ich habe beschlossen, einen Bot zu erstellen, der mich (oder auch nicht) an englische Wörter aus dem Wörterbuch erinnert.
Um ein Hantieren mit der Datenbank zu vermeiden, wird das Wörterbuch in einer Textdatei gespeichert und manuell aktualisiert.
In diesem Fall besteht die Aufgabe darin, die Grundlagen der Arbeit zu zeigen und nicht darin, ein zumindest teilweise fertiges Produkt herzustellen.

2. Was und wie zum ersten Mal ausprobieren

Erstellen wir einen Ordner C:poshtranslate
Schauen wir uns zunächst an, welche Art von Powershell wir haben. Starten wir ISE per Start-Run
Powershell ise
oder finden Sie Powershell ISE in installierten Programmen.
Nach dem Start öffnet sich der übliche bekannte „irgendein Editor“. Wenn kein Textfeld vorhanden ist, können Sie jederzeit auf „Datei – Neu erstellen“ klicken.

Schauen wir uns die Powershell-Version an – schreiben Sie in das Textfeld:

get-host 

und drücken Sie F5.

Powershell bietet das Speichern an – „Das Skript, das Sie ausführen möchten, wird gespeichert.“ Wir stimmen zu und speichern die Datei aus Powershell unter dem Namen in C: poshtranslate myfirstbotBT100.

Nach dem Start erhalten wir im unteren Textfenster eine Datentabelle:

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

Ich habe etwas 5.1, das reicht. Wenn Sie ein altes Windows 7/8 haben, ist das kein Problem – obwohl PowerShell auf Version 5 aktualisiert werden muss – z. B. Anleitung.

Geben Sie Get-Date in die Befehlszeile unten ein, drücken Sie die Eingabetaste, sehen Sie sich die Uhrzeit an und gehen Sie mit dem Befehl zum Stammordner
cd
und löschen Sie den Bildschirm mit dem cls-Befehl (nein, Sie müssen rm nicht verwenden)

Schauen wir uns nun an, was funktioniert und wie – schreiben wir nicht einmal den Code, sondern zwei Zeilen und versuchen zu verstehen, was sie bewirken. Kommentieren wir die Zeile mit get-host mit dem #-Symbol aus und fügen etwas hinzu.

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

(Interessant ist, dass es in der Dropdown-Liste für die Codeformatierung auf Habré zwei Dutzend Optionen gibt – Powershell ist jedoch nicht vorhanden. Dos ist vorhanden. Perl ist vorhanden.)

Und lassen Sie uns den Code ausführen, indem Sie in der GUI F5 oder „>“ drücken.

Wir erhalten die folgende Ausgabe:

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

Schauen wir uns nun diese beiden Zeilen und einige interessante Punkte an, damit wir in Zukunft nicht darauf zurückkommen.

Im Gegensatz zu Pascal (und nicht nur) versucht PowerShell selbst zu bestimmen, welcher Typ einer Variablen zugewiesen werden soll; weitere Details dazu finden Sie im Artikel Bildungsprogramm zum Tippen in Programmiersprachen
Wenn wir also eine $TimeNow-Variable erstellen und ihr den Wert des aktuellen Datums und der aktuellen Uhrzeit (Get-Date) zuweisen, müssen wir uns nicht allzu viele Gedanken darüber machen, welche Art von Daten dort vorhanden sein werden.

Es stimmt, diese Unwissenheit kann später weh tun, aber das ist etwas für später. Unten im Text finden Sie ein Beispiel.
Mal sehen, was wir haben. Lassen Sie uns ausführen (auf der Befehlszeile)

$TimeNow | Get-member

und erhalten Sie eine Seite mit unverständlichem Text

Beispiel für unverständlichen Text 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")...                                         

Wie Sie sehen können, wurde eine Variable vom Typ TypeName: System.DateTime mit einer Reihe von Methoden (im Sinne dessen, was wir mit diesem Variablenobjekt tun können) und Eigenschaften erstellt.

Lass uns anrufen $TimeNow.DayOfYear — wir erhalten die Zahl des Tages des Jahres.
Lass uns anrufen $TimeNow.DayOfYear | Get-Member - erhalten TypeName: System.Int32 und eine Gruppe von Methoden.
Lass uns anrufen $TimeNow.ToUniversalTime() - und erhalten Sie die Zeit in UTC

Debugger

Manchmal ist es notwendig, ein Programm bis zu einer bestimmten Zeile auszuführen und den Status des Programms in diesem Moment zu sehen. Zu diesem Zweck verfügt die ISE über eine Debug-Funktion – Haltepunkt umschalten
Setzen Sie irgendwo in der Mitte einen Haltepunkt, führen Sie diese beiden Zeilen aus und sehen Sie, wie der Bruch aussieht.

3. Die Interaktion mit dem Telegram-Bot verstehen

Natürlich wurde noch mehr Literatur über die Interaktion mit dem Bot geschrieben, mit allen Getpushs usw., aber die Frage der Theorie kann optional berücksichtigt werden.

In unserem Fall ist es notwendig:

  • Lernen Sie, etwas per Korrespondenz zu versenden
  • Lernen Sie, aus der Korrespondenz etwas herauszuholen

3.1 Lernen, etwas per Korrespondenz zu senden und daraus zu empfangen

Ein kleiner Code – Teil 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

und in der Russischen Föderation erhalten wir an dieser Stelle die Fehlermeldung Es konnte keine Verbindung zum Remote-Server hergestellt werden.

Oder wir erhalten es nicht – hängt vom Telekommunikationsbetreiber ab und davon, ob der Proxy konfiguriert ist und funktioniert
Nun muss nur noch ein Proxy hinzugefügt werden. Bitte beachten Sie, dass die Verwendung eines unverschlüsselten und in der Regel betrügerischen Proxys äußerst gesundheitsgefährdend ist.

Die Suche nach einem funktionierenden Proxy ist nicht sehr schwierig – die meisten veröffentlichten http-Proxys funktionieren. Ich denke, der fünfte hat bei mir funktioniert.

Syntax mit Proxy:

Invoke-WebRequest -Uri $URL4SEND -Proxy $MyProxy

Wenn Sie in Ihrem Chat mit einem Bot eine Nachricht erhalten, ist alles in Ordnung, Sie können weitermachen. Wenn nicht, fahren Sie mit dem Debuggen fort.

Sie können sehen, was aus Ihrem $URL4SEND-String wird, und versuchen, ihn wie folgt im Browser anzufordern:

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

3.2. Wir haben gelernt, wie man „etwas“ im Chat schreibt, jetzt versuchen wir es zu lesen

Fügen wir 4 weitere Zeilen hinzu und sehen durch |, was sich darin befindet Get-Mitglied

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

Das Interessanteste wird uns geboten

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

Mal sehen, was drin ist:

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

Wenn bei Ihnen alles funktioniert, erhalten Sie eine lange Schlange wie:

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

Glücklicherweise ist in dem zuvor veröffentlichten Artikel Telegram Bot für Systemadministratoren diese Zeile (ja, laut $MyMessageGet.RawContent | get-member ist System.String), wurde bereits zerlegt.

4. Verarbeiten Sie, was Sie erhalten (wir wissen bereits, wie man etwas sendet)

Wie bereits geschrieben hier, das Nötigste liegt im Inhalt. Schauen wir es uns genauer an.

Zuerst schreiben wir dem Bot über die Weboberfläche oder das Telefon noch ein paar Sätze

/message1
/message2
/message3

und schauen Sie im Browser nach der Adresse, die in der Variablen $URLGET gebildet wurde.

Wir werden so etwas sehen wie:

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

Was ist das? Ein komplexes Objekt aus Arrays von Objekten, das eine End-to-End-Nachrichten-ID, eine Chat-ID, eine Sende-ID und viele andere Informationen enthält.

Wir müssen jedoch nicht herausfinden, „was für ein Objekt das ist“ – ein Teil der Arbeit wurde bereits für uns erledigt. Mal sehen, was drin ist:

Empfangene Nachrichten lesen oder Teil 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. Was sollen wir jetzt dagegen tun?

Speichern wir die resultierende Datei unter dem Namen myfirstbotBT105 oder wie auch immer Ihnen am besten gefällt, ändern Sie den Titel und kommentieren Sie den gesamten bereits geschriebenen Code über aus

<#start comment 105 end comment 105#>

Jetzt müssen wir entscheiden, wo wir das Wörterbuch bekommen (also wo – auf der Festplatte in einer Datei) und wie es aussehen soll.

Natürlich können Sie direkt im Text des Skripts ein riesiges Wörterbuch schreiben, aber das ist völlig nebensächlich.
Schauen wir uns also an, womit Powershell normal funktionieren kann.
Im Allgemeinen ist es ihm egal, mit welcher Datei er arbeitet, für uns ist es egal.
Wir haben die Wahl: txt (Sie können, aber warum), csv, xml.
Können wir alle sehen? Lasst uns alle sehen.
Erstellen wir eine Klasse MyVocabClassExample1 und eine Variable $MyVocabExample1
Ich stelle fest, dass die Klasse ohne $ geschrieben ist

etwas Code Nr. 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

Versuchen wir, dies mit in Dateien zu schreiben exemplarisch.

Etwas Code Nr. 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

- und wir erhalten eine Fehlermeldung in der Zeile Out-File -FilePath $MyFilenameExample01 -InputObject -Append $MyVocabExample2.

Er möchte nicht hinzufügen, ah-ah, was für eine Schande.

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

Mal sehen was passiert. Tolle Textansicht – aber wie kann ich sie wieder exportieren? Sollte ich Texttrennzeichen wie Kommas einführen?

Und am Ende erhält man eine „Comma-Separated Values ​​(CSV)-Datei“ A Hör auf zu warten.
#

$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 

Wie Sie leicht erkennen können, unterscheidet sich MS nicht besonders durch seine Logik; für ein ähnliches Verfahren wird in einem Fall -FilePath verwendet, in einem anderen -Path.

Außerdem verschwand in der dritten Datei die russische Sprache, in der vierten Datei stellte sich heraus ... nun, etwas ist passiert. #TYPE System.Object[] 00
# „Count“, „Length“, „LongLength“, „Rank“, „SyncRoot“, „IsReadOnly“, „IsFixedSize“, „IsSynchronized“
#
Schreiben wir es ein wenig um:

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

Es scheint geholfen zu haben, aber mir gefällt das Format immer noch nicht.

Mir gefällt vor allem nicht, dass ich Zeilen von einem Objekt nicht direkt in eine Datei einfügen kann.
Können wir übrigens, da wir angefangen haben, in Dateien zu schreiben, ein Startprotokoll führen? Wir haben time als Variable, wir können den Dateinamen festlegen.

Es gibt zwar noch nichts zu schreiben, aber Sie können darüber nachdenken, wie Sie die Protokolle am besten drehen.
Versuchen wir es zunächst einmal mit XML.

Etwas 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

Der Export in XML hat viele Vorteile – Lesbarkeit, Export des gesamten Objekts und keine Notwendigkeit, ein Nachtrag durchzuführen.

Versuchen XML-Datei lesen.

Eine kleine Lektüre aus XML

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

Kehren wir zur Aufgabe zurück. Wir haben eine Testdatei geschrieben, sie gelesen, das Speicherformat ist klar, bei Bedarf können Sie einen separaten kleinen Dateieditor schreiben, um Zeilen hinzuzufügen und zu löschen.

Ich möchte Sie daran erinnern, dass die Aufgabe darin bestand, einen kleinen Trainingsbot zu bauen.

Arbeitsformat: Ich sende den Befehl „Beispiel“ an den Bot, der Bot sendet mir ein zufällig ausgewähltes Wort und eine Transkription und nach 10 Sekunden sendet er mir eine Übersetzung und einen Kommentar. Wir wissen, wie man Befehle liest, wir würden auch gerne lernen, wie man Proxys automatisch auswählt und überprüft und Nachrichtenzähler in Vergessenheit bringt.

Lassen Sie uns alles auskommentieren, was zuvor als unnötig auskommentiert wurde, kommentieren Sie die jetzt unnötigen Beispiele mit txt und csv aus und speichern Sie die Datei als Version B106

Oh ja. Senden wir noch einmal etwas an den Bot.

6. Versand von Funktionen und mehr

Bevor Sie den Empfang verarbeiten, müssen Sie eine Funktion erstellen, um „zumindest etwas“ außer einer Testnachricht zu senden.

Natürlich haben wir im Beispiel nur einen Versand und nur eine Verarbeitung, aber was ist, wenn wir dasselbe mehrmals tun müssen?

Es ist einfacher, eine Funktion zu schreiben. Wir haben also eine aus der Datei gelesene Variable vom Typ Objekt $MyVocabExample4AsArray in Form eines Arrays mit bis zu zwei Elementen.
Lass uns lesen gehen.

Gleichzeitig beschäftigen wir uns mit der Uhr; wir werden sie später brauchen (tatsächlich werden wir sie in diesem Beispiel nicht brauchen :)

Etwas Code Nr. 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
}

Wie Sie leicht erkennen können, ruft die Funktion $MyToken und $MyChatID auf, die zuvor fest codiert waren.

Dies ist nicht erforderlich, und wenn $MyToken für jeden Bot eins ist, ändert sich $MyChatID je nach Chat.

Da es sich jedoch um ein Beispiel handelt, werden wir es vorerst ignorieren.

Da $MyVocabExample4AsArray kein Array ist, obwohl es einem sehr ähnlich ist Du kannst es nicht einfach nehmen Fordern Sie die Länge an.

Wieder einmal müssen wir etwas tun, was nicht möglich ist – einen Fallschirm springen, der nicht dem Code entspricht – ihn nehmen und zählen

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

Zufällig interessante Funktion. Nehmen wir an, wir möchten 0 oder 1 erhalten (wir haben nur zwei Elemente im Array). Wenn wir die Grenzen 0..1 festlegen, erhalten wir „1“?
Nein – wir bekommen es nicht, wir haben ein spezielles Beispiel. Beispiel 2: Holen Sie sich eine zufällige Ganzzahl zwischen 0 und 99. Get-Random – Maximum 100
Daher müssen wir für 0..1 die Größe 0..2 einstellen, mit der maximalen Elementanzahl = 1.

7. Verarbeitung eingehender Nachrichten und maximale Warteschlangenlänge

Wo haben wir vorhin aufgehört? wir haben die empfangene Variable $MyMessageGet
und daraus erhaltenes $Content4Pars01, von dem wir an den Elementen des Content4Pars01.result-Arrays interessiert sind

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

Senden wir dem Bot /message10, /message11, /message12, /word und noch einmal /word und /hello.
Mal sehen, was wir bekommen haben:

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

Lassen Sie uns alles durchgehen, was wir erhalten haben, und eine Antwort senden, wenn die Nachricht /word war
Der Fall des Konstrukts, das manche als „if-elseif“ bezeichnen, wird in Powershell aufgerufen über Schalter. Gleichzeitig verwendet der folgende Code den -Wildcard-Schlüssel, was völlig unnötig und sogar schädlich ist.

Etwas Code Nr. 7.1

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

Lassen Sie uns das Skript ein paar Mal ausführen. Bei jedem Ausführungsversuch erhalten wir zweimal dasselbe Wort, insbesondere wenn uns bei der Implementierung von „Random“ ein Fehler unterlaufen ist.

Aber hör auf. Wir haben /word nicht erneut gesendet. Warum wird die Nachricht erneut verarbeitet?

Die Warteschlange zum Senden von Nachrichten an den Bot hat eine endliche Länge (100 oder 200 Nachrichten, glaube ich) und muss manuell geleert werden.

Das steht natürlich in der Dokumentation, aber man muss sie unbedingt lesen!

In diesem Fall benötigen wir den Parameter ?chat_id und &timeout, &limit, &parse_mode=HTML und &disable_web_page_preview=true werden noch nicht benötigt.

Dokumentation für Telegramm-API ist hier
Es heißt in Weiß und Englisch:
Bezeichner des ersten Updates, das zurückgegeben werden soll. Muss um eins größer sein als der höchste der Bezeichner zuvor empfangener Updates. Standardmäßig beginnen Aktualisierungen mit dem frühesten
unbestätigt Update werden zurückgegeben. Ein Update gilt als bestätigt, sobald getUpdates mit einem aufgerufen wird Offset höher als seine update_id. Der negative Offset kann angegeben werden, um Updates ab -offset update vom Ende der Update-Warteschlange abzurufen. Alle vorherigen Updates werden vergessen.

Schauen wir uns Folgendes an:

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

Ja, und wir werden es zurücksetzen und die Funktion ein wenig umschreiben. Wir haben zwei Möglichkeiten: Wir übergeben die gesamte Nachricht an die Funktion und verarbeiten sie vollständig in der Funktion oder geben nur die Nachrichten-ID an und setzen sie zurück. Das zweite sieht zum Beispiel einfacher aus.

Bisher sah unsere Abfragezeichenfolge „Alle Nachrichten“ so aus

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

und es wird so aussehen

$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 verbietet Ihnen, alle Nachrichten zunächst zu empfangen, zu bearbeiten und erst nach erfolgreicher Bearbeitung unbestätigt -> bestätigt anzufordern.

Warum ist es sinnvoll, nach Abschluss aller Bearbeitungen eine Bestätigung anzurufen? Ein Fehler ist mitten in der Ausführung möglich, und wenn beispielsweise bei einem kostenlosen Chatbot das Fehlen einer einzigen Nachricht nichts Besonderes ist, kann das Ergebnis schlechter ausfallen, wenn Sie das Gehalt oder die Kartentransaktion einer anderen Person verarbeiten.

Noch ein paar Codezeilen

$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. Anstelle einer Schlussfolgerung

Grundfunktionen – Nachrichten lesen, Warteschlange zurücksetzen, aus Datei lesen und in Datei schreiben – werden ausgeführt und angezeigt.

Es bleiben nur noch vier Dinge zu tun:

  • Senden der richtigen Antwort auf eine Anfrage im Chat
  • Senden einer Antwort an JEDEN Chat, zu dem der Bot hinzugefügt wurde
  • Code in einer Schleife ausführen
  • Starten eines Bots über den Windows-Planer.

Alle diese Aufgaben sind einfach und können leicht erledigt werden, indem man die Dokumentation zu Parametern wie liest
Set-ExecutionPolicy Unrestricted und -ExecutionPolicy Bypass
Zyklus der Form

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

Vielen Dank an alle, die gelesen haben.

Source: habr.com

Kommentar hinzufügen