Im Gespräch mit einem Freund erfuhr ich überraschend, dass die Kinder in der 8.-10. Klasse an ihrer Schule überhaupt nicht in Programmierung unterrichtet werden. Nur Word, Excel und das war's. Weder Logo, noch Pascal, noch sogar VBA für Excel.
Ich war sehr überrascht, öffnete das Internet und begann zu lesen —
Eine der Aufgaben der Fachschule ist es, die Erziehung einer neuen Generation zu fördern, die in ihrer Entwicklung und Lebensweise den Bedingungen der Informationsgesellschaft entspricht.
Dieser Kurs wird es ermöglichen, die Kenntnisse der Schüler über die grundlegenden Strukturen der Programmiersprache Pascal in der Praxis zu festigen. (aus dem Programm eines Gymnasiums aus dem Jahr 2017)
Schließlich entschied ich mich, ein paar Stunden zu investieren und ein Beispiel zu skizzieren, wie "man einen einfachen Bot für Schüler erstellt".
Unter dem Abschnitt geht es darum, wie man einen weiteren einfachen Bot in PowerShell schreibt und ihn ohne Webhook, öffentliche IPs, dedizierte Server, bereitgestellte virtuelle Maschinen in der Cloud und dergleichen zum Laufen bringt — auf einem normalen Heim-PC mit einem normalen Windows.
TLDR: Noch ein langweiliger Artikel mit grammatikalischen und faktischen Fehlern, nichts zu lesen, kein Humor, keine Bilder.
Im Artikel gibt es nichts Neues, fast alles, was geschrieben wurde, war früher schon auf Habr zu finden, zum Beispiel in den Artikeln und .
Darüber hinaus ist der Artikel absichtlich überflüssig, um nicht jedes Mal auf Lehrliteratur verweisen zu müssen. Es gibt keine Hinweise auf Band 4, PowerShell Deep Dives oder The 5 Pillars of the AWS Well-Architected Framework im Text.
Anstelle eines Vorworts kann man dies überspringen
Lassen Sie uns mutig überspringenIm Jahr 2006 brachte Microsoft PowerShell 1.0 für das damalige Windows XP, Vista und Server 2003 heraus. In gewisser Weise ersetzte es Dinge wie CMD-Batch-Skripte, VB-Skripte, Windows Script Host und JScript.
Selbst jetzt kann PowerShell nur als der nächste Schritt nach Optionen wie Logo betrachtet werden, statt der vermutlich immer noch verwendeten Delphi (oder etwas älteren), trotz der Verfügbarkeit von Schleifen, Klassen, Funktionen, Aufrufen der MS GUI, und so weiter.
PowerShell wird relativ selten verwendet, man trifft es nur in Form von PowerShell Core, VMware vSphere PowerCLI, Azure PowerShell, MS Exchange, Desired State Configuration, und einem weiteren Dutzend seltener verwendeter Programme und Funktionen. Möglicherweise wird es mit der Veröffentlichung von , aber das ist nicht sicher.
PowerShell hat auch drei große Vorteile:
- Es ist relativ einfach, es gibt eine Menge Literatur und Beispiele darüber, sogar auf Russisch, zum Beispiel ein Artikel über Foreach – aus dem Buch – über den Unterschied zwischen () und {}
- Es kommt zusammen mit dem Editor , im Paket mit Windows. Dort gibt es sogar einen kleinen Debugger.
- Es lassen sich leicht aufrufen .
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 – einen installierten und konfigurierten Freegate im Browser, in einigen komplizierten Fällen zusammen mit Symple DNS Crypt
- Einen funktionierenden Telegram-Client auf dem Telefon
- Grundlegendes Verständnis – was eine Variable, ein Array und eine Schleife ist.
Gelesene Artikel – und
1. Erstellen wir einen weiteren Testbot.
Da das ohnehin jeder weiß und es bereits gemacht wurde, kann es auch übersprungen werden.Wie im Artikel oben erwähnt – Zuerst einmal, der Bot für Telegram – ist nach wie vor eine Anwendung, die auf Ihrer Seite läuft und Anfragen an die Telegram Bot API sendet. Die API ist verständlich – der Bot ruft eine bestimmte URL mit Parametern auf, und Telegram antwortet mit einem JSON-Objekt.
Verwandte Probleme: Wenn Sie aus unerfindlichen Gründen einen bestimmten Code aus einem JSON-Objekt nehmen und ihn irgendwie (nicht absichtlich) zur Ausführung senden – wird der Code bei Ihnen ausgeführt.
Der Prozess der Erstellung ist in den beiden obigen Artikeln beschrieben, aber ich wiederhole: In Telegram öffnen wir Kontakte, suchen nach @botfather, sagen ihm /newbot, erstellen den Bot Botfortest12344321, nennen ihn Mynext1234bot und erhalten eine Nachricht mit einem einzigartigen Schlüssel im Format 1234544311:AbcDefNNNNNNNNNNNNN
Hüten Sie den Schlüssel und geben Sie ihn nicht weiter!
Danach kann der Bot konfiguriert werden, zum Beispiel kann man 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, finden dort @Botfortest12344321 (die Suche unbedingt mit @ beginnen), klicken auf «Start» und schreiben dem Bot «/Ehre den Robotern». Das Zeichen / ist obligatorisch, Anführungszeichen sind nicht notwendig.
Der Bot wird natürlich nichts antworten.
Überprüfen wir, ob der Bot erstellt wurde – öffnen wir ihn.
:AbcDefNNNNNNNNNNNNN/getMe
wobei 1234544311:AbcDefNNNNNNNNNNNNN – der zuvor erhaltene Schlüssel ist,
und wir erhalten eine Zeile im Format
{«ok»:true,«result»:{«»}}
Der erste geheime Satz (Token) ist vorhanden. Jetzt müssen wir die zweite geheime Zahl herausfinden – die ID des Chats mit dem Bot. Jeder Chat, jede Gruppe usw. sind individuell und haben ihre eigene Nummer (manchmal mit einem Minus — für offene Gruppen). Um diese Nummer zu erfahren, müssen wir im Browser (es ist nicht unbedingt notwendig, im Browser zu sein, aber für ein besseres Verständnis kann man damit beginnen) die Adresse anfordern (wobei 1234544311:NNNNNNNNN Ihr Token ist)
https://api.telegram.org/bot1234544311:NNNNNNNNN/getUpdates
und eine Antwort in der Form erhalten
{«ok»:true,«result»:[{«update_id»:…,… chat«:{«id»:123456789
Wir brauchen genau die chat_id.
Prüfen wir, ob wir manuell in den Chat schreiben können: Rufen wir aus dem Browser die Adresse auf
https://api.telegram.org/botdeintoken/sendMessage?chat_id=123456789&text="Life is directed motion"Wenn eine Nachricht von dem Bot in deinen Chat gekommen ist – okay, dann gehst du zum nächsten Schritt.
So kannst du (über den Browser) immer überprüfen, wo die Probleme liegen – bei dir beim Generieren des Links oder ob etwas irgendwo blockiert ist und nicht funktioniert.
Was du wissen solltest, bevor du weiterliest
In Telegram gibt es mehrere Arten von Gruppenchats (offene, geschlossene). Für diese Chats unterscheiden sich einige Funktionen (zum Beispiel Id), was manchmal zu Problemen führen kann.
Nehmen wir an, es ist Ende 2019, und sogar der Held unserer Zeit, der weithin bekannte Mensch-Orchester (Administrator, Jurist, IT-Sicherheitsexperte, Programmierer und praktisch MVP) Jewgenij W. kann die Variable $i von einem Array unterscheiden, hat Schleifen erlernt und wird in den nächsten paar Jahren wahrscheinlich Chocolatey beherrschen, und dann wird er auch und erreichen.
1. Lass uns überlegen, was unser Bot tun wird
Ich hatte keine Ideen, ich musste nachdenken. Einen Notizbuch-Bot hatte ich bereits geschrieben. Einen Bot zu machen, „der etwas irgendwohin weiterleitet“, wollte ich nicht. Für die Nutzung von Azure benötigt man eine Kreditkarte, aber woher hat ein Schüler die? Man muss jedoch erwähnen, dass alles nicht so schlecht ist: Die großen Clouds bieten einen kostenlosen Testzeitraum an (aber trotzdem wird eine Kreditkartennummer benötigt – und davon wird, glaube ich, ein Dollar abgebucht. Ich erinnere mich nicht, ob er später zurückkam.)
Ohne AI macht es nicht so viel Spaß, einen Bot-Oberschlauer-Verseschreiber zu kreieren.
Ich habe mich entschieden, einen Bot zu machen, der mir (oder nicht mir) englische Wörter aus dem Wörterbuch in Erinnerung ruft.
Das Wörterbuch wird, um sich nicht mit einer Datenbank herumzuschlagen, in einer Textdatei liegen und manuell ergänzt.
In diesem Fall besteht die Aufgabe darin, die Grundlagen der Arbeit zu zeigen und nicht ein teilweise fertiges Produkt zu erstellen.
2. Wir probieren, was und wie beim ersten Mal
Erstellen wir den Ordner C:poshtranslate
Zuerst schauen wir uns an, was wir für PowerShell haben. Lassen Sie uns ISE über Ausführen starten.
powershell ise
oder wir finden PowerShell ISE in den installierten Programmen.
Nach dem Start öffnet sich der gewohnte «irgendein Editor». Wenn kein Textfeld vorhanden ist, können wir immer «Datei — neu erstellen» drücken.
Lassen Sie uns die Version von PowerShell betrachten — wir schreiben ins Textfeld:
get-host
und drücken F5.
PowerShell wird uns fragen, ob wir speichern möchten — «Das Skript, das Sie ausführen möchten, wird gespeichert.», wir stimmen zu und speichern die Datei aus PowerShell mit dem Namen myfirstbotBT100.
Nach dem Start erhalten wir im unteren Textfenster eine Tabelle mit Daten:
Name : Windows PowerShell ISE Host
Version : 5.1.(usw.)
Ich habe 5.1 mit irgendetwas, das ist ausreichend. Wenn Sie Windows 7/8 verwenden, ist das nicht schlimm — allerdings sollte PowerShell auf Version 5 aktualisiert werden, zum Beispiel über .
Geben wir in die Eingabeaufforderung unten Get-Date ein, drücken Enter, sehen wir uns die Zeit an und wechseln mit dem Befehl
cd
und reinigen den Bildschirm mit dem Befehl cls (nein, rm sollte nicht verwendet werden)
Jetzt prüfen wir, was und wie funktioniert — wir schreiben nicht einmal einen Code, sondern zwei Zeilen und versuchen zu verstehen, was sie tun. Wir kommentieren die Zeile mit ‘get-host’ mit dem Symbol # und fügen ein wenig hinzu.
# Пример шаблона бота
# get-host
<# это пример многострочного комментария #>
$TimeNow = Get-Date
$TimeNow
(Was interessant ist. In der Dropdown-Liste zur Codeformatierung auf Habr gibt es zwei Dutzend Varianten — aber PowerShell ist nicht dabei. Dos ist dabei. Perl ist dabei.)
Und wir starten den Code, indem wir F5 drücken oder «>» aus der GUI auswählen.
Wir erhalten die Ausgabe:
Samstag, 8. Dezember 2019 21:00:50 (oder so ähnlich)
Jetzt lassen Sie uns diese beiden Zeilen und einige interessante Punkte klären, 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 darüber steht in dem Artikel
Deshalb müssen wir uns keine besonderen Gedanken machen, wenn wir die Variable $TimeNow erstellen und ihr den Wert des aktuellen Datums und der Uhrzeit (Get-Date) zuweisen.
Es kann jedoch schmerzhaft sein, nicht zu wissen, was hier passiert, aber das ist später. Unten im Text wird ein Beispiel folgen.
Schauen wir uns an, was wir bekommen 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
---- ---------- ----------
Hinzufügen <b>Method </b>datetime Hinzufügen(timespan Wert)
..
Anzeigehinweis NoteProperty DisplayHintType DisplayHint=DateTime
Datum <b>Eigenschaft </b>datetime Datum {get;}
Jahr Eigenschaft int Jahr {get;}
..
DateTime ScriptProperty System.Object Datum {get=if ((& { Set-StrictMode -Version 1; $this.DisplayHint }) -ieq "Date")...
Wie man sieht, wurde eine Variable des Typs TypeName: System.DateTime mit vielen Methoden (im Sinne von, was wir mit diesem Objektvariable tun können) und Eigenschaften erstellt.
Lassen Sie uns aufrufen $TimeNow.DayOfYear — wir erhalten die Tagesnummer im Jahr.
Lassen Sie uns aufrufen $TimeNow.DayOfYear | Get-Member — wir erhalten Typename: System.Int32 und die Gruppe von Methoden.
Lassen Sie uns aufrufen $TimeNow.ToUniversalTime() — und wir erhalten die Zeit in UTC
Debugger
Manchmal ist es notwendig, das Programm bis zu einer bestimmten Zeile auszuführen und den Status des Programms zu diesem Zeitpunkt zu überprüfen. Dafür gibt es in ISE die Funktion Debug – toggle break point.
Setzen Sie einen Haltepunkt irgendwo in der Mitte, führen Sie diese beiden Zeilen aus und sehen Sie, wie der Halt aussieht.
3. Wir befassen uns mit der Interaktion mit dem Telegram-Bot
Natürlich gibt es über die Interaktion mit dem Bot, mit allen getpush usw. noch viel mehr Literatur, jedoch kann die theoretische Frage fakultativ behandelt werden.
In unserem Fall müssen wir:
- Lernen, etwas in den Chat zu senden
- Lernen, etwas aus dem Chat zu erhalten
3.1 Lernen, etwas in den Chat zu senden und auch daraus zu erhalten
Ein wenig Code – Teil 3
Write-output "Das 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 RF an dieser Stelle erhalten wir den Fehler Unable to connect to the remote server.
Oder wir erhalten nichts — es hängt vom Mobilfunkanbieter ab und davon, ob der Proxy eingerichtet ist und funktioniert.
Nun bleibt nur noch, einen Proxy hinzuzufügen. Beachten Sie, dass die Verwendung eines unverschlüsselten und allgemein unseriösen Proxys äußerst riskant für Ihre Gesundheit ist.
Die Aufgabe, einen funktionsfähigen Proxy zu finden, ist nicht sehr schwierig — der Großteil der veröffentlichten HTTP-Proxys funktioniert. Meiner hat anscheinend beim fünften Mal funktioniert.
Syntax mit Proxy:
Invoke-WebRequest -Uri $URL4SEND -Proxy $MyProxy
Wenn Sie eine Nachricht in Ihren Chat mit dem Bot erhalten haben — dann ist alles in Ordnung, Sie können weitermachen. Wenn nicht — fahren Sie mit dem Debugging fort.
Sie können sehen, wie sich Ihre Zeile $URL4SEND ändert und versuchen, sie im Browser aufzurufen, 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 dort über | get-member herauskommt.
$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 bietet uns
Content Property string Content {get;}
ParsedHtml Property mshtml.IHTMLDocument2 ParsedHtml {get;}
RawContent Property string RawContent {get;set;}Schauen wir uns an, was darin ist:
Write-Host "ParsedHtml"
$MyMessageGet.ParsedHtml # hier ist etwas Interessantes
Write-Host "RawContent"
$MyMessageGet.RawContent # und hier ist ebenfalls etwas Interessantes, das zudem lesbar ist.
Write-Host "Content"
$MyMessageGet.Content
Wenn bei Ihnen alles funktioniert, erhalten Sie eine lange Zeichenfolge wie diese:
{"ok":true,"result":[{"update_id":12345678,
"message":{"message_id":3,"from":{"id"Gut, in einem früheren Artikel über den Telegram-Bot für Systemadministratoren wurde diese Zeile (ja, laut $MyMessageGet.RawContent | get-member — ist dies System.String), bereits behandelt.
4. Verarbeiten Sie das Erhaltene (etwas zu senden, können wir bereits)
Wie bereits erwähnt , liegt das Wichtigste im Content. Schauen wir uns das genauer an.
Zuerst schreiben wir dem Bot noch ein paar Sätze aus der Weboberfläche oder vom Handy
/message1
/message2
/message3und schauen wir über den Browser auf die Adresse, die in der Variable $URLGET erstellt wurde.
Wir werden 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 Array-Objekten, das eine durchgehende Nachrichten-ID, eine Chat-ID, eine Absender-ID und noch viele weitere 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. Schauen wir uns an, was da drinnen ist:
Lesen der 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 sollen wir jetzt damit machen
Wir speichern die erhaltene Datei unter dem Namen myfirstbotBT105 oder wie auch immer Ihnen am besten gefällt, ändern die Überschrift und kommentieren den bereits geschriebenen Code aus
<#start comment 105 end comment 105#>
Jetzt müssen wir uns entscheiden, wo wir das Wörterbuch beziehen (woher — von der Festplatte in einer Datei) und wie es aussehen wird.
Natürlich kann man ein riesiges Wörterbuch direkt im Text des Skripts erstellen, aber das ist wirklich nicht sinnvoll.
Deshalb schauen wir, womit PowerShell standardmäßig arbeiten kann.
Tatsächlich ist es ihm egal, mit welcher Datei er arbeitet, uns jedoch nicht.
Zur Auswahl haben wir: txt (geht, aber wozu), csv, xml.
Oder wir schauen uns alles an. Schauen wir uns alles an.
Wir erstellen die Klasse MyVocabClassExample1 und die Variable $MyVocabExample1
Ich bemerke, dass die Klasse ohne $ geschrieben wird
ein wenig Code #5
Schreibe-Host "Dies 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 - ein jüngster Fall mit SSD HPE. Zunächst wollte ich dieses Element nicht hinzufügen, habe es dann aber doch geschrieben 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 Birnenbaum (ˈpɛər) und der Strauch sind eine Art der Gattung Pyrus."
# $MyVocabExample1.$VocWordID = 2
Lass uns versuchen, das in Dateien nach .
Ein bisschen Code #5.1
Write-Host $ScriptDir # ich hoffe, $ScriptDir hast du nicht kommentiert
$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 möchte nicht hinzufügen, oi oi, wie ärgerlich.
$MyVocabExample3AsArray = @($MyVocabExample1,$MyVocabExample2)
Out-File -FilePath $MyFilenameExample02 -InputObject $MyVocabExample3AsArray
notepad $MyFilenameExample02
Schauen wir mal, was herausgekommen ist. Wunderschöner Textansicht — aber wie exportiert man ihn wieder zurück? Muss man irgendwelche Texttrennzeichen, zum Beispiel Kommas, eingeben?
Und am Ende ein "Datei mit Trennzeichen — Kommas, comma-separated values (CSV)" erhalten. .
#
$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 einfach zu sehen ist, hat MS nicht besonders viel Logik gezeigt, denn für ein ähnliches Verfahren wird in einem Fall -FilePath verwendet, im anderen -Path.
Außerdem ist in der dritten Datei die russische Sprache verloren gegangen, in der vierten Datei hat es… nun, es ist etwas herausgekommen. #TYPE System.Object[] 00
# „Count“,»Length»,«LongLength»,«Rank»,«SyncRoot»,«IsReadOnly»,«IsFixedSize»,«IsSynchronized»
#
Lass uns das ein wenig umschreiben:
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 mir nicht, dass ich die Zeilen aus dem Objekt nicht direkt in die Datei legen kann.
Übrigens, da wir schon damit angefangen haben, in Dateien zu schreiben – vielleicht sollten wir ein Startprotokoll führen? Die Zeit haben wir als Variable und wir können auch den Dateinamen festlegen.
Wahr ist, dass wir bisher nichts zu schreiben haben, aber wir können überlegen, wie wir die Protokolle besser rotieren können.
Lass uns erstmal xml ausprobieren.
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 im xml hat viele Vorteile – Lesbarkeit, Export des gesamten Objekts und kein uppend erforderlich.
Lass es uns versuchen .
Ein wenig Lesen aus xml
$MyFilenameExample06 = $ScriptDir + "Example06.xml"
$MyVocabExample4AsArray = Import-Clixml -Path $MyFilenameExample06
# $MyVocabExample4AsArray
# $MyVocabExample4AsArray[0]
# und ein wenig über vollkommen unerwartete Nuancen. Powershell verhält sich manchmal nicht so, wie man es erwarten würde.
# zum Beispiel unterscheiden sich diese beiden Ausgaben
# Write-Output $MyVocabExample4AsArray
# write-host $MyVocabExample4AsArray
Kehren wir zur Aufgabe zurück. Wir haben eine Testdatei erstellt, gelesen, das Speicherformat ist klar, bei Bedarf können wir einen kleinen Dateieditor für das Hinzufügen und Entfernen von Zeilen schreiben.
Ich erinnere daran, dass die Aufgabe darin bestand, einen kleinen Lernbot 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 die Übersetzung und einen Kommentar. Wir können die Befehle lesen, müssen aber natürlich auch lernen, Proxys automatisch zu finden und zu prüfen und die Nachrichtenzähler in die Vergessenheit zu schicken.
Lass uns alles, was wir zuvor auskommentiert haben, wieder aktivieren, die inzwischen unnötigen Beispiele mit txt und csv auskommentieren und die Datei als Version B106 speichern.
Ach ja. Lass uns dem Bot etwas noch einmal senden.
6. Sendung aus Funktionen und nicht nur
Bevor wir mit der Verarbeitung des Empfangs beginnen, müssen wir eine Funktion implementieren, die „irgendetwas“ sendet, abgesehen von der Testnachricht.
Natürlich wird in unserem Beispiel nur eine Sendung und nur aus einer Verarbeitung erfolgen; was ist, wenn wir mehrmals das Gleiche tun müssen?
Es ist einfacher, eine Funktion zu schreiben. So haben wir eine Objektvariable $MyVocabExample4AsArray, die aus der Datei gelesen wurde, in Form eines Arrays mit insgesamt zwei Elementen.
Gleichzeitig klären wir die Zeit, die wir später benötigen werden (in diesem Beispiel ist es tatsächlich nicht notwendig 🙂
Ein wenig Code #6.1
Schreibe-Ausgabe "Das ist Teil 6"
$Zeitzone = (Get-ZeitZone)
WENN($Zeitzone UnterstütztTagessparzeit -eq $Wahr){
$ZeitAnpassung = ($Zeitzone.BasisUtcOffset.TotalSeconds + 3600) } # angepasste Zeit
SONST{$ZeitAnpassung = ($Zeitzone.BasisUtcOffset.TotalSeconds)
}
funktion MeineErsteFunktion($EinBeispielFürFunktion1){
$AktuelleZeit = Hol-Datum
$AktuelleZeit.ToUniversalTime()
# $MeinText02 = $AktuelleZeit + " " + $EinBeispielFürFunktion1 # und hier würden wir einen Fehler bekommen
$MeinText02 = $EinBeispielFürFunktion1 + " " + $AktuelleZeit # hier würden wir keinen Fehler bekommen, wer errät warum - der hat es gut gemacht.
$URLZuSendenVonFunktion = "https://api.telegram.org/bot$MeinToken/sendMessage?chat_id=$MeinChatID&text=$MeinText02"
Invoke-WebRequest -Uri $URLZuSendenVonFunktion -Proxy $MeinProxy
}
Wie leicht zu sehen ist, wird in der Funktion $MeinToken und $MeinChatID aufgerufen, die zuvor fest zugewiesen wurden.
Das sollte man nicht tun, und wenn $MeinToken für jeden Bot gleich ist, wird sich $MeinChatID je nach Chat ändern.
Da dies jedoch ein Beispiel ist, ignorieren wir das vorerst.
Da $MeinVocabBeispiel4AlsArray kein Array ist, obwohl es sehr danach aussieht, kann man nicht einfach so die Länge anfragen.
Wir müssen erneut das tun, was man nicht tun sollte — nach den Regeln abspringen — einfach zählen.
Ein wenig Code #6.2
$MaxRandomBeispiel = 0
foreach ($Obj in $MeinVocabBeispiel4AlsArray) {
$MaxRandomBeispiel ++
}
Schreibe-Ausgabe $MaxRandomBeispiel
$ZufallsBeispiel = Hol-Zufallszahl -Minimum 0 -Maximum ($MaxRandomBeispiel)
$TextFürBeispiel1 = $MeinVocabBeispiel4AlsArray[$ZufallsBeispiel].Original
# MeineErsteFunktion($TextFürBeispiel1)
# oder in einer Zeile
# MeineErsteFunktion($MeinVocabBeispiel4AlsArray[Hol-Zufallszahl -Minimum 0 -Maximum ($MaxRandomBeispiel -1)].Beispiel)
# Rate selbst, welches Beispiel leichter von Fremden gelesen wird.
Zufällig . Angenommen, wir möchten 0 oder 1 erhalten (wir haben insgesamt zwei Elemente im Array). Wenn wir die Grenzen 0..1 festlegen — werden wir "1" erhalten?
nein — wir werden es nicht bekommen, wir haben spezifisch das Beispiel Beispiel 2 gegeben: Erhalte eine zufällige Ganzzahl zwischen 0 und 99 Hol-Zufallszahl -Maximum 100
Daher müssen wir für 0..1 die Größe 0..2 festlegen, wobei die maximale Elementnummer = 1 ist.
7. Verarbeitung der eingehenden Nachrichten und maximale Warteschlangenlänge
Worin waren wir zuvor stehen geblieben? Wir haben die erhaltene Variable $MeineNachrichtErhalten
und die aus ihr erhaltene $Inhalt4Pars01, aus der wir die Elemente des Arrays Content4Pars01.result interessieren.
$Inhalt4Pars01.result[0].update_id
$Inhalt4Pars01.result[0].message
$Inhalt4Pars01.result[0].message.text Wir senden an den Bot /message10, /message11, /message12, /word und noch einmal /word und /hallo.
Sehen wir uns an, was wir erhalten haben:
$Inhalt4Pars01.result[0].message.text
$Inhalt4Pars01.result[2].message.text Wir durchlaufen alles, was wir erhalten haben, und senden eine Antwort, wenn die Nachricht /word war.
die Konstruktion case of, die einige als if-elseif beschreiben, wird in PowerShell aufgerufen . Im untenstehenden Code wird der Schlüssel -wildcard verwendet, was absolut nicht notwendig und sogar schädlich sein kann.
Ein wenig Code #7.1
Write-Output "Das ist Teil 7"
Foreach ($Result in $Content4Pars01.result) # Ja, es kann schneller gemacht werden
{
switch -wildcard ($Result.message.text)
{
"\/word" {MyFirstFunction($TextForExample1)}
}
}
Wir führen das Skript ein paar Mal aus. Wir erhalten jedes Mal dasselbe Wort bei jedem Ausführungsversuch, insbesondere wenn wir bei der Implementierung von random einen Fehler gemacht haben.
Aber Moment. Wir haben doch noch kein weiteres Mal /word gesendet, warum wird die Nachricht also erneut verarbeitet?
Die Warteschlange zum Senden von Nachrichten an den Bot hat eine begrenzte Länge (es scheint 100 oder 200 Nachrichten zu sein), und sie muss manuell gereinigt 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 zurzeit nicht erforderlich sind.
Die Dokumentation zu Auf Englisch steht dort klar:
Identifier für das erste zurückgegebene Update. Muss um eins größer sein als das höchste unter den Identifikatoren zuvor erhaltener Updates. Standardmäßig werden Updates, die mit dem frühesten beginnen, zurückgegeben.
unbestätigt Update. Ein Update gilt als bestätigt, sobald getUpdates mit einem offset höheren als seiner update_id aufgerufen wird.. Der negative Offset kann angegeben werden, um Updates ab -offset Update vom Ende der Updates-Warteschlange zu erhalten. 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 wir setzen zurück - wir schreiben die Funktion ein wenig um. Wir haben zwei Optionen - entweder die gesamte Nachricht an die Funktion übergeben und sie vollständig innerhalb der Funktion verarbeiten oder nur die ID der Nachricht übergeben und diese zurücksetzen. Zum Beispiel sieht die zweite Option einfacher aus.
Früher sah unsere Anfrage "aller 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, diese zu verarbeiten und erst nach erfolgreicher Verarbeitung unbestätigt -> bestätigt zu fragen.
Warum es sinnvoll ist, die Bestätigung nach Abschluss aller Verarbeitungen aufzurufen? Ein Fehler kann mitten in der Ausführung auftreten, und wenn es beispielsweise für einen kostenlosen Chatbot nicht so schlimm ist, eine einzelne Nachricht zu übersehen, kann das Ergebnis viel schlimmer sein, wenn Sie jemandes Gehalt oder eine Kartentransaktion verarbeiten.
Noch ein paar Zeilen Code
$LastMessageId = ($Content4Pars01.result | select -last 1).update_id # Fehler an dieser Stelle sollen selbst behoben werden.
$URLGET1 = "https://api.telegram.org/bot$mytoken/getUpdates?offset=$LastMessageId&limit=100"
Invoke-WebRequest -Uri $URLGET1 -Method Get -Proxy $MyProxy
8. Fazit
Die Hauptfunktionen — das Lesen von Nachrichten, das Zurücksetzen der Warteschlange, das Lesen aus einer Datei und das Schreiben in eine Datei sind umgesetzt und gezeigt worden.
Es sind nur noch vier Dinge zu erledigen:
- die richtige Antwort auf die Anfrage im Chat senden
- die Antwort in JEDEN Chat senden, in den der Bot hinzugefügt wurde
- den Code in einer Schleife ausführen
- den Bot aus dem Windows-Planer starten.
Alle diese Aufgaben sind einfach und können leicht umgesetzt werden, indem man die Dokumentation zu Parametern wie
Set-ExecutionPolicy Unrestricted und -ExecutionPolicy Bypass
Schleifenart
$TimeToSleep = 3 # Abfragen 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 hierhin gelesen haben.
Quelle: habr.com
