In einem Gespräch mit einem Freund wurde mir plötzlich klar, dass Schüler in den Klassen 8 bis 10 an ihrer Schule überhaupt nicht im Programmieren unterrichtet werden. Nur Word, Excel und das war's. Weder Logo, noch sogar Pascal oder VBA für Excel.
Ich war sehr überrascht, habe das Internet durchforstet und angefangen zu lesen —
Eine der Aufgaben einer spezialisierten Schule ist es, die Ausbildung einer neuen Generation zu fördern, die in ihrer Entwicklung und Lebensweise den Bedingungen der Informationsgesellschaft entspricht.
Dieser Kurs wird den Schülern helfen, ihre Kenntnisse der grundlegenden Konstruktionsprinzipien der Programmiersprache Pascal praktisch zu festigen. (aus dem Programm einer bestimmten Gymnasiums von 2017)
Letztendlich beschloss ich, ein paar Stunden zu investieren und ein Beispiel dafür zu skizzieren, "wie man einen einfachen Bot für Schüler erstellt."
Ich werde erläutern, wie man einen weiteren einfachen Bot in Powershell schreibt und ihn dazu bringt, ohne Webhook, öffentliche IP-Adressen, dedizierte Server oder in der Cloud bereitgestellte virtuelle Maschinen zu funktionieren — ganz einfach auf einem normalen Heim-PC mit gewöhnlichem Windows.
Zusammenfassung: Noch ein langweiliges Artikel mit grammatikalischen und faktischen Fehlern, kaum lesenswert, kein Humor, keine Bilder.
Der Artikel bietet nichts Neues, fast alles Geschriebene wurde bereits früher auf Habr veröffentlicht, zum Beispiel in anderen Artikeln. und .
Darüber hinaus ist der Artikel absichtlich übermäßig ausführlich, um nicht ständig auf Lehrbücher verweisen zu müssen. Es gibt keine Verweise auf die 'Bande 4', 'PowerShell Deep Dives' oder sagen wir 'The 5 Pillars of the AWS Well-Architected Framework' im Text.
Anstelle eines Vorworts kann man das überspringen
Wir überspringen es einfachIm Jahr 2006 veröffentlichte Microsoft PowerShell 1.0 für das damalige Windows XP, Vista und den Server 2003. In gewisser Weise ersetzte es Dinge wie CMD-Batch-Skripte, VB-Skripte, Windows Script Host und JScript.
Selbst heute kann PowerShell nur als nächster Schritt nach Varianten von Logo betrachtet werden, anstatt dass es wohl immer noch verwendete Delphi (oder noch ältere Versionen) gibt, trotz der Verfügbarkeit von Schleifen, Klassen, Funktionen, MS GUI-Aufrufen, usw.
PowerShell wird relativ selten verwendet; man begegnet ihm höchstens in Form von PowerShell Core, VMware vSphere PowerCLI, Azure PowerShell, MS Exchange, Desired State Configuration, und noch ein Dutzend anderer selten verwendeter Programme und Funktionen. Vielleicht wird es eine neue Blütezeit mit der Einführung von , aber das ist ungewiss.
PowerShell hat auch drei große Vorteile:
- Es ist relativ einfach, darüber gibt es eine Menge Literatur und Beispiele, sogar auf Russisch, zum Beispiel der Artikel über Foreach – aus einem Buch. – über den Unterschied zwischen () und {}.
- Es kommt zusammen mit dem Editor , im Paket mit Windows. Dort gibt es sogar einen Debugger.
- Von ihm lassen sich leicht .
0. Vorbereitung.
Wir benötigen:
- einen PC mit Windows (ich habe Windows 10)
- Irgendeinen Internetzugang (zum Beispiel über NAT)
- Für diejenigen, die eingeschränkten Zugang zu Telegram haben – ein installierter und konfigurierter Freegate im Browser, in einigen komplizierten Fällen zusammen mit Symple DNS Crypt.
- Einen funktionierenden Telegram-Client auf dem Handy.
- Ein grundlegendes Verständnis der Grundlagen – was eine Variable, ein Array, eine Schleife ist.
Offene und gelesene Artikel – und
1. Erstellen wir einen weiteren Testbot.
Da dies ohnehin alle wissen und es bereits war, kann auch das übersprungen werden.Wie im obigen Artikel gesagt – Zunächst einmal ist ein Bot für Telegram – eine Anwendung, die auf Ihrer Seite läuft und Anfragen an die Telegram Bot API stellt. Die API ist klar – der Bot macht Anfragen an eine bestimmte URL mit Parametern, und Telegram antwortet mit einem JSON-Objekt.
Verwandte Probleme: Wenn Sie auf unbekannte Weise einen Code aus einem JSON-Objekt entnehmen und ihn unbeabsichtigt ausführen — wird der Code bei Ihnen ausgeführt.
Der Prozess zur Erstellung ist in den beiden oben genannten Artikeln beschrieben, aber ich wiederhole: Im Telegramm öffnen wir die Kontakte, suchen nach @botfather, sagen ihm /newbot, erstellen den Bot Botfortest12344321, benennen ihn Mynext1234bot und erhalten eine Nachricht mit einem einzigartigen Schlüssel wie 1234544311:AbcDefNNNNNNNNNNNNN.
Bewahren Sie den Schlüssel gut auf und geben Sie ihn nicht weiter!
Danach können Sie den Bot konfigurieren, zum Beispiel das Hinzufügen zu Gruppen verbieten, aber in den ersten Schritten ist das nicht notwendig.
Fragen wir BotFather nach «/mybot» und passen die Einstellungen an, falls etwas nicht gefällt.
Öffnen wir wieder die Kontakte, suchen dort nach @Botfortest12344321 (mit @ zu beginnen ist obligatorisch), klicken Sie auf «Start» und schreiben Sie dem Bot «/Ehre den Robotern». Das Zeichen / ist obligatorisch, die Anführungszeichen sind nicht notwendig.
Der Bot wird natürlich nicht antworten.
Überprüfen wir, ob der Bot erstellt wurde — öffnen wir ihn.
:AbcDefNNNNNNNNNNNNN/getMe
wo 1234544311:AbcDefNNNNNNNNNNNNN der zuvor erhaltene Schlüssel ist,
und wir erhalten eine Zeile wie
{«ok»:true,«result»:{«»}}
Wir haben die erste geheime Phrase (Token). Jetzt müssen wir die zweite geheime Zahl herausfinden – die Chat-ID mit dem Bot. Jeder Chat, jede Gruppe usw. ist individuell und hat eine eigene Nummer (manchmal mit einem Minus – für öffentliche Gruppen). Um diese Nummer zu erfahren, müssen wir in einem Browser (obwohl es nicht unbedingt im Browser sein muss, aber für ein besseres Verständnis kann damit begonnen werden) die Adresse anfragen (wobei 1234544311:NNNNNNNNN Ihr Token ist).
https://api.telegram.org/bot1234544311:NNNNNNNNN/getUpdates
und eine Antwort im folgenden Format erhalten
{«ok»:true,«result»:[{«update_id»:…,… chat«:{«id»:123456789
Wir brauchen genau die chat_id.
Lassen Sie uns überprüfen, ob wir manuell in den Chat schreiben können: Rufen Sie die Adresse aus dem Browser auf
https://api.telegram.org/botIhrToken/sendMessage?chat_id=123456789&text="Life is directed motion"Wenn eine Nachricht vom Bot in Ihren Chat gekommen ist – gut, dann gehen Sie zur nächsten Stufe.
Auf diese Weise (über den Browser) können Sie immer prüfen, wo das Problem liegt – bei Ihnen bei der Generierung des Links oder ob etwas blockiert ist und nicht funktioniert.
Was Sie wissen sollten, bevor Sie weiterlesen
In Telegram gibt es verschiedene Arten von Gruppenchats (offene, geschlossene). Für diese Chats unterscheiden sich einige Funktionen (z.B. ID), was manchmal zu Problemen führen kann.
Lassen Sie uns annehmen, dass wir uns am Ende des Jahres 2019 befinden. Selbst unser Zeitgenosse, der weithin bekannte Alleskönner (Administrator, Jurist, Informationssicherheitsexperte, Programmierer und praktisch MVP) Jewgeni W. kann die Variable $i von einem Array unterscheiden, hat Schleifen gemeistert und vielleicht wird er in den nächsten Jahren auch Chocolatey beherrschen, und dann wird er bis und kommen.
1. Lassen Sie uns überlegen, was unser Bot tun wird.
Ich hatte keine Ideen, also musste ich nachdenken. Ich hatte bereits einen Bot als Notizblock programmiert. Die Idee eines Bots, der "etwas irgendwohin weiterleitet", war mir nicht ansprechend. Um Azure zu nutzen, braucht man eine Kreditkarte, aber woher hat ein Schüler die? Es ist jedoch nicht so schlimm: Die großen Cloud-Anbieter bieten einen kostenlosen Testzeitraum (aber eine Kreditkartennummer ist trotzdem erforderlich – und es wird, glaube ich, ein Dollar davon abgebucht. Ich erinnere mich nicht, ob er später zurückkam.)
Ohne KI ist es nicht so spannend, einen Bot-Dödel-Poesiebot zu erstellen.
Ich beschloss, einen Bot zu erstellen, der mir (oder nicht mir) englische Wörter aus einem Wörterbuch erinnert.
Das Wörterbuch wird in einer Textdatei gespeichert, um den Aufwand mit einer Datenbank zu vermeiden, und wird manuell ergänzt.
In diesem Fall besteht die Aufgabe darin, die Grundlagen der Arbeit zu demonstrieren und nicht ein wenigstens teilweise fertiges Produkt zu erstellen.
2. Wir probieren alles zum ersten Mal aus
Lassen Sie uns den Ordner C:poshtranslate erstellen
Zunächst sehen wir uns an, was wir für PowerShell haben, und starten das ISE über Ausführen.
powershell ise
oder wir finden PowerShell ISE in den installierten Programmen.
Nach dem Start öffnet sich der gewohnte „was auch immer für ein Editor“, falls kein Textfeld zu sehen ist, können Sie immer auf „Datei — neu erstellen“ klicken.
Schauen wir uns die Version von PowerShell an — schreiben wir in das Textfeld:
get-host
und drücken Sie F5.
PowerShell wird fragen, ob Sie speichern möchten — „Das Skript, das Sie gerade ausführen möchten, wird gespeichert.“, wir stimmen zu und speichern die Datei aus PowerShell in C:poshtranslate mit dem Namen myfirstbotBT100.
Nach dem Start erhalten wir im unteren Textfeld eine Datentabelle:
Name : Windows PowerShell ISE Host
Version : 5.1.(usw.)
Ich habe 5.1 mit etwas, das reicht aus. Wenn Sie Windows 7/8 haben, ist das nicht schlimm — obwohl PowerShell auf Version 5 aktualisiert werden muss — beispielsweise durch .
Geben Sie in der unteren Eingabeaufforderung Get-Date ein, drücken Sie Enter und schauen Sie sich die Uhrzeit an, und wechseln Sie mit dem Befehl
cd
in das Wurzelverzeichnis und reinigen Sie den Bildschirm mit dem Befehl cls (nein, rm ist nicht erforderlich).
Jetzt überprüfen wir, was und wie es funktioniert – wir schreiben sogar keinen Code, sondern zwei Zeilen, und versuchen zu verstehen, was sie tun. Wir kommentieren die Zeile mit dem get-host-Symbol # aus und fügen etwas hinzu.
# Пример шаблона бота
# get-host
<# это пример многострочного комментария #>
$TimeNow = Get-Date
$TimeNow
(Interessanterweise gibt es im Dropdown-Menü der Codeformatierung auf Habr zwei Dutzend Optionen – Powershell ist jedoch nicht dabei. Dos ist dabei. Perl ist dabei.)
Und wir führen den Code aus, indem wir F5 oder „>“ aus der GUI drücken.
Wir erhalten die Ausgabe:
Samstag, 8. Dezember 2019 21:00:50 (oder so ähnlich)
Jetzt werden wir diese beiden Zeilen und einige interessante Aspekte näher betrachten, damit wir später nicht darauf zurückkommen müssen.
Im Gegensatz zu Pascal (und nicht nur) versucht PowerShell selbst zu bestimmen, welchen Typ es der Variablen zuweisen soll; mehr dazu steht in dem Artikel
Daher brauchen wir uns keine Sorgen zu machen, welchen Datentyp die Variable $TimeNow hat, wenn wir ihr den aktuellen Zeitpunkt (Get-Date) zuweisen.
Das Unwissen darüber kann später schmerzhaft sein, aber das ist später. Im Text gibt es ein Beispiel.
Schauen wir uns an, was wir erhalten haben. Führen wir (in der Eingabeaufforderung) aus
$TimeNow | Get-Memberund erhalten eine Seite mit unverständlichem Text
Beispiel unverständlicher Text Nummer 1
PS C:> $TimeNow | Get-member
TypeName: System.DateTime
Name MemberType Definition
---- ---------- ----------
Add <b>Methode </b>datetime Add(timespan value)
..
DisplayHint NoteProperty DisplayHintType DisplayHint=Datum
Datum <b>Eigenschaft </b>datetime Datum {get;}
Jahr Property int Jahr {get;}
..
DatumZeit ScriptProperty System.Object DatumZeit {get=if ((& { Set-StrictMode -Version 1; $this.DisplayHint }) -ieq "Datum")...
Wie zu sehen ist, wurde eine Variable des Typs TypeName: System.DateTime mit einer Vielzahl von Methoden (im Sinne von dem, was wir mit diesem Objekt tun können) und Eigenschaften erstellt.
Rufen wir auf $TimeNow.DayOfYear — wir erhalten die Nummer des Tages im Jahr.
Rufen wir auf $TimeNow.DayOfYear | Get-Member — wir erhalten TypeName: System.Int32 und eine Gruppe von Methoden.
Rufen wir auf $TimeNow.ToUniversalTime() — und erhalten die Zeit in UTC.
Debugger
Manchmal ist es notwendig, ein Programm bis zu einer bestimmten Zeile auszuführen und den Zustand des Programms zu diesem Zeitpunkt zu betrachten. Dazu gibt es in ISE die Funktion Debug - Toggle Breakpoint.
Setzen Sie einen Haltepunkt irgendwo in der Mitte, führen Sie diese beiden Zeilen aus und sehen Sie, wie der Halt aussieht.
3. Wir beschäftigen uns mit der Interaktion mit dem Telegram-Bot
Natürlich gibt es viel mehr Literatur zur Interaktion mit dem Bot, zu allen GetPush-Befehlen usw., aber die theoretische Frage kann fakultativ betrachtet werden.
In unserem Fall ist es notwendig:
- Etwas in den Chat zu senden
- Etwas aus dem Chat zu empfangen
3.1 Wir lernen, etwas in den Chat zu senden und aus ihm zu empfangen
Ein wenig Code – Teil 3
Schreiben Sie-Ausgabe "Dies ist Teil 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 = "Das Leben ist gerichtete Bewegung - " + $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 den Fehler "Unable to connect to the remote server."
Oder wir erhalten keinen - hängt vom Anbieter ab und davon, ob der Proxy konfiguriert und funktionsfähig ist.
Nun bleibt uns nichts anderes übrig, als einen Proxy hinzuzufügen. Beachten Sie - die Nutzung eines unverschlüsselten und allgemein unsicheren Proxys ist äußerst riskant für Ihre Sicherheit.
Die Suche nach einem funktionierenden Proxy ist nicht sehr schwierig - die meisten veröffentlichten HTTP-Proxys funktionieren. Bei mir hat scheinbar der fünfte in der Reihe funktioniert.
Syntax mit der Verwendung eines Proxys:
Invoke-WebRequest -Uri $URL4SEND -Proxy $MyProxy
Wenn Sie eine Nachricht in Ihren Chat mit dem Bot erhalten haben - dann läuft alles gut, Sie können fortfahren. Wenn nicht - setzen Sie die Fehlersuche fort.
Sie können sehen, wie Ihre String $URL4SEND aussieht und versuchen, sie im Browser zu öffnen, zum Beispiel so:
$URL4SEND2 = '"'+$URL4SEND+'"'
start chrome $URL4SEND2
3.2. Wir haben gelernt, "etwas" in den Chat zu schreiben, jetzt versuchen wir zu lesen.
Fügen wir noch 4 Zeilen hinzu und schauen wir, was sich hinter | get-member verbirgt.
$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 bereitgestellt von
Content Property string Content {get;}
ParsedHtml Property mshtml.IHTMLDocument2 ParsedHtml {get;}
RawContent Property string RawContent {get;set;}Schauen wir, was darin enthalten ist:
Write-Host "ParsedHtml"
$MyMessageGet.ParsedHtml # hier ist es interessant
Write-Host "RawContent"
$MyMessageGet.RawContent # und hier ist es auch interessant, zudem lesbar.
Write-Host "Content"
$MyMessageGet.Content
Wenn alles bei Ihnen funktioniert, werden Sie eine lange Zeichenkette wie folgt erhalten:
{"ok":true,"result":[{"update_id":12345678,
"message":{"message_id":3,"from":{"id"Glücklicherweise wurde diese Zeile in einem vorherigen Artikel über Telegram-Bots für Systemadministratoren bereits behandelt (ja, laut $MyMessageGet.RawContent | get-member — das ist System.String), wurde bereits erläutert.
4. Verarbeiten Sie das erhaltene (wir können bereits etwas senden)
Wie bereits erwähnt , liegt das Wichtigste im Content. Lassen Sie es uns genauer ansehen.
Schreiben wir zuerst dem Bot ein paar Sätze über die Weboberfläche oder das Telefon
/message1
/message2
/message3und schauen wir über den Browser auf die Adresse, die in der Variablen $URLGET gebildet wurde.
Wir werden etwas Ähnliches sehen:
{"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, das eine durchgehende Nachrichten-ID, eine Chat-ID, eine Versand-ID und eine Menge weiterer Informationen enthält.
Es ist jedoch nicht nötig, uns mit "Was ist das für ein Objekt?" zu beschäftigen - ein Teil der Arbeit wurde bereits für uns erledigt. Sehen wir uns an, was sich darin befindet:
Wir lesen die empfangenen Nachrichten oder Teil 4
Write-Host "Das ist Teil 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 machen wir jetzt damit?
Wir speichern die erhaltene Datei unter dem Namen myfirstbotBT105 oder einem anderen, der Ihnen besser gefällt, ändern den Titel und kommentieren den bereits geschriebenen Code aus.
<#start comment 105 end comment 105#>
Jetzt müssen wir uns entscheiden, wo wir das Wörterbuch hernehmen (naja, wo – auf der Festplatte in einer Datei) und wie es aussehen wird.
Natürlich kann man ein riesiges Wörterbuch direkt im Skript schreiben, aber das ist nicht der richtige Weg.
Deshalb schauen wir uns an, womit PowerShell standardmäßig arbeitet.
Eigentlich ist es ihm egal, mit welcher Datei er arbeitet, uns interessiert das jedoch.
Zur Auswahl haben wir: txt (möglich, aber warum?), csv, xml.
Oder wir können alle anschauen. Lassen Sie uns alle betrachten.
Erstellen wir die Klasse MyVocabClassExample1 und die Variable $MyVocabExample1.
Ich weise darauf hin, dass die Klasse ohne $ geschrieben wird.
Ein wenig Code #5
write-host "Das ist Teil 5"
class MyVocabClassExample1 {
[string]$Original # Wort
[string]$Transcript
[string]$Translate
[string]$Example
[int]$VocWordID # Ein sehr interessanter Punkt. Die Verwendung von int mit seinen Einschränkungen kann manchmal zu wilden Konsequenzen führen, zum Beispiel der jüngste Fall mit SSD HPE. Ursprünglich wollte ich dieses Element nicht hinzufügen, habe es dann aber doch ergänzt und kommentiert.
}
$MyVocabExample1 = [MyVocabClassExample1]::new()
$MyVocabExample1.Original = "Apple"
$MyVocabExample1.Transcript = "[ ˈapəl ]"
$MyVocabExample1.Translate = "Apfel"
$MyVocabExample1.Example = "Ein Apfel ist eine süße, essbare Frucht, die von einem Apfelbaum (Malus domestica) produziert wird."
# $MyVocabExample1.$VocWordID = 1
$MyVocabExample2 = [MyVocabClassExample1]::new()
$MyVocabExample2.Original = "Pear"
$MyVocabExample2.Transcript = "[ pe(ə)r ]"
$MyVocabExample2.Translate = "Birne"
$MyVocabExample2.Example = "Der Birnbaum (/ˈpɛər/) und der Strauch sind eine Art der Gattung Pyrus."
# $MyVocabExample1.$VocWordID = 2
Versuchen wir, dies in Dateien zu schreiben. .
Ein wenig Code #5.1
Write-Host $ScriptDir # ich hoffe, $ScriptDir haben Sie nicht auskommentiert
$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 einen Fehler in der Zeile Out-File -FilePath $MyFilenameExample01 -InputObject -Append $MyVocabExample2.
Es wird nicht hinzugefügt, oh wie ärgerlich.
$MyVocabExample3AsArray = @($MyVocabExample1,$MyVocabExample2)
Out-File -FilePath $MyFilenameExample02 -InputObject $MyVocabExample3AsArray
notepad $MyFilenameExample02
Schauen wir, was entstanden ist. Ein schöner Text! — aber wie exportiere ich ihn zurück? Soll ich irgendwie Texttrennzeichen wie Kommas eingeben?
Und am Ende eine „Datei mit Trennzeichen – Kommas, comma-separated values (CSV) A .
#
$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 leicht zu sehen ist, hat MS nicht besonders durchdacht. Für ein ähnliches Verfahren wird in einem Fall -FilePath, in einem anderen -Path verwendet.
Außerdem fehlt in der dritten Datei die russische Sprache, in der vierten Datei... nun, es ist etwas herausgekommen. #TYPE System.Object[] 00
# „Count“,»Length»,«LongLength»,«Rank»,«SyncRoot»,«IsReadOnly»,«IsFixedSize»,«IsSynchronized»
#
Lass uns etwas umformulieren:
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 das Format gefällt mir trotzdem nicht.
Besonders gefällt es mir nicht, dass ich die Zeilen aus dem Objekt nicht direkt in die Datei schreiben kann.
Übrigens, da wir schon dabei sind, Dateien zu schreiben — sollten wir vielleicht ein Startprotokoll führen? Die Zeit haben wir als Variable, und das Dateinamen können wir festlegen.
Es gibt zwar noch nichts zu schreiben, aber wir können überlegen, wie wir die Protokollrotation besser gestalten.
Versuchen wir es vorerst mit XML.
Ein wenig 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 nur Vorteile — Lesbarkeit, Export des gesamten Objekts, und man muss kein Append durchführen.
Lass es uns probieren .
Ein wenig Lesevorgang aus XML
$MyFilenameExample06 = $ScriptDir + "Example06.xml"
$MyVocabExample4AsArray = Import-Clixml -Path $MyFilenameExample06
# $MyVocabExample4AsArray
# $MyVocabExample4AsArray[0]
# und ein wenig über die nicht-so-eindeutigen Nuancen. Powershell verhaltet sich manchmal nicht ganz so, wie man es erwarten würde.
# Zum Beispiel habe ich hier zwei unterschiedliche Ausgaben
# Write-Output $MyVocabExample4AsArray
# write-host $MyVocabExample4AsArray
Kommen wir zurück zur Aufgabe. Wir haben die Testdatei erstellt, gelesen, das Speicherformat ist klar, falls nötig kann man einen kleinen separaten Editor zum Hinzufügen und Entfernen von Zeilen schreiben.
Ich erinnere daran, dass die Aufgabe war, einen kleinen Lehrbot zu erstellen.
Arbeitsformat: Ich sende dem Bot den Befehl «Beispiel», der Bot sendet mir ein zufällig ausgewähltes Wort und die Transkription, und nach 10 Sekunden schickt er die Übersetzung und einen Kommentar. Wir können Befehle lesen, wir sollten natürlich auch lernen, automatisch Proxys auszuwählen und zu überprüfen und die Nachrichtenstatistiken ins Nichts zurückzusetzen.
Lassen Sie uns alles, was wir zuvor als unwichtig kommentiert haben, wieder aktivieren und die nicht mehr benötigten Beispiele mit txt und csv kommentieren, und die Datei als Version B106 speichern.
Ach, ja. Lassen Sie uns dem Bot noch einmal etwas senden.
6. Versand aus Funktionen und nicht nur
Bevor wir mit der Verarbeitung der Eingabe beginnen, müssen wir eine Funktion erstellen, die "irgendetwas" sendet, abgesehen von der Testnachricht.
In unserem Beispiel gibt es natürlich nur eine Sendung und nur eine Verarbeitung. Was ist, wenn wir das mehrmals wiederholen müssen?
Es ist einfacher, eine Funktion zu schreiben. Wir haben also eine Variable vom Typ Objekt $MyVocabExample4AsArray, die aus einer Datei als Array mit genau zwei Elementen gelesen wurde.
Gleichzeitig beschäftigen wir uns mit den Zeitzonen, das werden wir später brauchen (obwohl wir es in diesem Beispiel eigentlich nicht benötigen 🙂
Ein bisschen Code #6.1
Write-Output "Dies ist Teil 6"
$Timezone = (Get-TimeZone)
IF($Timezone.SupportsDaylightSavingTime -eq $True){
$TimeAdjust = ($Timezone.BaseUtcOffset.TotalSeconds + 3600) } # angepasste Zeit
ELSE{$TimeAdjust = ($Timezone.BaseUtcOffset.TotalSeconds)
}
function MyFirstFunction($SomeExampleForFunction1){
$TimeNow = Get-Date
$TimeNow.ToUniversalTime()
# $MyText02 = $TimeNow + " " + $SomeExampleForFunction1 # und hier würden wir einen Fehler erhalten
$MyText02 = $SomeExampleForFunction1 + " " + $TimeNow # hier nicht, wer erraten kann, warum - ist super.
$URL4SendFromFunction = "https://api.telegram.org/bot$MyToken/sendMessage?chat_id=$MyChatID&text=$MyText02"
Invoke-WebRequest -Uri $URL4SendFromFunction -Proxy $MyProxy
}
Wie leicht zu sehen ist, wird in der Funktion $MyToken und $MyChatID aufgerufen, die zuvor fest zugewiesen wurden.
Das sollte nicht so gemacht werden, und wenn $MyToken für jeden Bot gleich ist, wird sich $MyChatID je nach Chat ändern.
Da dies jedoch ein Beispiel ist, ignorieren wir das vorerst.
Da $MyVocabExample4AsArray kein Array ist, obwohl es sehr ähnlich aussieht, kann man einfach nicht seine Länge anfragen.
Man wird erneut gezwungen, das zu tun, was man nicht tun sollte – nach dem Kodex abzuspringen – einfach zu zählen.
Ein wenig 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)
# oder in einer Zeile
# MyFirstFunction($MyVocabExample4AsArray[Get-Random -Minimum 0 -Maximum ($MaxRandomExample -1)].Example)
# Raten Sie selbst, welches Beispiel leichter von Außenstehenden zu lesen ist.
Zufällig . Angenommen, wir möchten 0 oder 1 erhalten (wir haben nur zwei Elemente im Array). Wenn wir die Grenzen 0..1 setzen – erhalten wir dann „1“?
Nein – das werden wir nicht, unser Beispiel ist speziell gegeben. Beispiel 2: Holen Sie sich eine Zufallszahl zwischen 0 und 99 Get-Random -Maximum 100
Deshalb müssen wir für 0..1 die Größe 0..2 angeben, wobei die maximale Elementnummer = 1 ist.
7. Verarbeitung eingehender Nachrichten und maximale Warteschlangenlänge
Worauf sind wir vorher gestoßen? Wir haben die erhaltene Variable $MyMessageGet.
und die daraus erhaltene $Content4Pars01, wobei uns die Elemente des Arrays Content4Pars01.result interessieren.
$Content4Pars01.result[0].update_id
$Content4Pars01.result[0].message
$Content4Pars01.result[0].message.text Wir senden an den Bot /message10, /message11, /message12, /word und nochmal /word sowie /hallo.
Schauen wir, was wir erhalten haben:
$Content4Pars01.result[0].message.text
$Content4Pars01.result[2].message.text Durchlaufen wir alles, was wir erhalten haben, und senden eine Antwort, wenn die Nachricht /word war.
Die Konstruktionsweise ist die fallabhängige Verarbeitung, was einige als if-elseif beschreiben; in PowerShell wird dies . Dabei wurde im folgenden Code der Schlüssel -wildcard verwendet, was nicht unbedingt erforderlich ist und sogar schädlich sein kann.
Ein wenig Code #7.1
Write-Output "Das ist Teil 7"
Foreach ($Result in $Content4Pars01.result) # Ja, es könnte schneller gehen
{
switch -wildcard ($Result.message.text)
{
"/word" {MyFirstFunction($TextForExample1)}
}
}
Lassen Sie das Skript ein paar Mal laufen. Wir erhalten bei jedem Versuch dasselbe Wort, besonders wenn wir einen Fehler bei der Umsetzung von random gemacht haben.
Aber Stopp. Wir haben doch /word nicht noch einmal gesendet, warum wird die Nachricht dann erneut verarbeitet?
Die Warteschlange für das Senden von Nachrichten an den Bot hat eine feste Länge (es scheint 100 oder 200 Nachrichten zu sein), und sie muss manuell gelöscht werden.
In der Dokumentation ist das natürlich beschrieben, aber man muss sie auch lesen!
In diesem Fall benötigen wir den Parameter ?chat_id, während &timeout, &limit, &parse_mode=HTML und &disable_web_page_preview=true momentan nicht erforderlich sind.
Die Dokumentation zu Auf Englisch steht dort klar geschrieben:
Identifier des ersten Updates, das zurückgegeben werden soll. Muss um eins höher sein als der höchste unter den Identifikatoren der zuvor empfangenen Updates. Standardmäßig werden Updates ab dem frühesten
unbestätigt Update zurückgegeben. Ein Update gilt als bestätigt, sobald getUpdates mit einem offset höheren als seiner update_id. Der negative Offset kann angegeben werden, um Updates ab dem -Offset Update vom Ende der Updates-Warteschlange abzurufen. Alle vorherigen Updates werden vergessen.
Schauen wir uns an:
$Content4Pars01.result[0].update_id
$Content4Pars01.result[1].update_id
$Content4Pars01.result | select -last 1
($Content4Pars01.result | select -last 1).update_idUnd lassen Sie uns das zurücksetzen – wir schreiben die Funktion ein wenig um. Wir haben zwei Optionen – entweder das gesamte Nachrichtenspektrum an die Funktion übergeben und es dort vollständig verarbeiten, oder nur die ID der Nachricht übergeben und diese zurücksetzen. Das zweite sieht im Beispiel einfacher aus.
Früher sah unsere Abfrage für "alle Nachrichten" so aus:
$URLGET = "https://api.telegram.org/bot$MyToken/getUpdates"und 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 hindert Sie daran, zuerst alle Nachrichten abzurufen, sie zu verarbeiten und erst nach erfolgreicher Verarbeitung den Status von unconfirmed auf confirmed zu ändern.
Warum macht es Sinn, die Bestätigung nach Abschluss aller Verarbeitungen anzufordern? Ein Fehler kann mitten in der Ausführung auftreten, und während es für einen kostenlosen Chatbot nicht so wichtig ist, dass eine einzelne Nachricht übersprungen wird, könnte das Ergebnis viel schlimmer sein, wenn Sie beispielsweise das Gehalt oder eine Kreditkartentransaktion einer Person verarbeiten.
Noch ein paar Zeilen Code
$LastMessageId = ($Content4Pars01.result | select -last 1).update_id #Der Fehler an dieser Stelle sollte selbst behoben werden.
$URLGET1 = "https://api.telegram.org/bot$mytoken/getUpdates?offset=$LastMessageId&limit=100"
Invoke-WebRequest -Uri $URLGET1 -Method Get -Proxy $MyProxy
8. Statt eines Schlusses
Die Hauptfunktionen – Lesen von Nachrichten, Zurücksetzen der Warteschlange, Lesen aus einer Datei und Schreiben in eine Datei wurden ausgeführt und gezeigt.
Es bleiben nur noch vier Dinge zu tun:
- das Senden der richtigen Antwort auf eine Anfrage im Chat
- das Senden einer Antwort in JEDEN Chat, in den der Bot hinzugefügt wurde
- das Ausführen von Code in einer Schleife
- den Bot über den Windows-Taskplaner starten.
All diese Aufgaben sind einfach und lassen sich leicht mit Hilfe der Dokumentation zu Parametern wie
Set-ExecutionPolicy Unrestricted und -ExecutionPolicy Bypass
Schleifen dieser Art
$TimeToSleep = 3 # Abfrage alle 3 Sekunden
$TimeToWork = 10 # Minuten
$HowManyTimes = $TimeToWork*60/$TimeToSleep # Zähler für die Schleife
$MainCounter = 0
for ($MainCounter=0; $MainCounter -le $HowManyTimes) {
sleep $TimeToSleep
$MainCounter ++
Vielen Dank an alle, die bis zum Ende gelesen haben.
Quelle: habr.com
