Le modèle du bot de télégramme le plus simple pour les écoliers de la 7e à la 9e année sur Powershell

Au cours de conversations avec un ami, j'ai soudainement appris que les enfants de la 8e à la 10e année de leur école n'apprenaient pas du tout la programmation. Word, Excel et tout. Pas de logo, pas même Pascal, pas même VBA pour Excel.

J'ai été très surpris, j'ai ouvert Internet et j'ai commencé à lire -
L'une des tâches d'une école spécialisée est de promouvoir l'éducation d'une nouvelle génération qui répond aux conditions de la société de l'information dans son niveau de développement et son mode de vie.
Ce cours permettra aux étudiants de consolider par la pratique leurs connaissances des constructions de base du langage de programmation Pascal. (du programme de certains gymnases pour 2017)

En fin de compte, j'ai décidé de passer quelques heures et d'esquisser un exemple de « comment créer un robot simple pour les écoliers ».

Ci-dessous, vous trouverez comment écrire un autre robot simple dans Powershell et le faire fonctionner sans webhook, sans adresses IP blanches, sans serveurs dédiés, sans machines virtuelles déployées dans le cloud, etc. - sur un PC domestique classique avec Windows standard.

TLDR : Encore un article ennuyeux avec des erreurs grammaticales et factuelles, rien à lire, pas d'humour, pas d'images.

Il n'y a rien de nouveau dans l'article, presque tout ce qui a été écrit auparavant l'a déjà été sur Habré, par exemple dans des articles Instructions : Comment créer des robots dans Telegram и Bot Telegram pour l'administrateur système.
De plus, l’article est volontairement redondant pour ne pas faire à chaque fois référence à la littérature pédagogique. Il n'y a aucune référence à Gang 4, PowerShell Deep Dives ou, disons, aux 5 piliers du framework AWS Well-Architected dans le texte.

Au lieu d'une préface, vous pouvez sauter

N'hésitez pas à sauterEn 2006, Microsoft a publié PowerShell 1.0 pour Windows XP, Vista et Server 2003. D'une certaine manière, il a remplacé des éléments tels que les scripts cmdbat, les scripts vb, Windows Script Host et JScript.

Même maintenant, PowerShell ne peut être considéré que comme la prochaine étape après les options Logo, au lieu de Delphi probablement encore utilisé (ou quelque chose de plus ancien), malgré la présence de boucles, classes, fonctions, appels MS GUI, Intégration Git et ainsi de suite.

Powershell est relativement rarement utilisé ; vous ne pouvez le rencontrer que sous la forme de PowerShell Core, VMware vSphere PowerCLI, Azure PowerShell, MS Exchange, Desired State Configuration, Accès Web PowerShell et une douzaine de programmes et de fonctions plus rarement utilisés. Peut-être qu'il aura un second souffle avec la sortie WSL2, mais ce n'est pas exactement.

Powershell présente également trois grands avantages :

  1. C'est relativement simple, il y a beaucoup de littérature et d'exemples à ce sujet, et même en russe, par exemple, un article sur Foreach - tiré du livre PowerShell en profondeur - à propos de la différence () et {}
  2. Il va avec l'éditeur ISE, inclus avec Windows. Il y a même une sorte de débogueur.
  3. Il est facile d'appeler depuis là composants pour construire une interface graphique.

0. Préparation.

Nous aurons besoin:

  • PC Windows (j'ai Windows 10)
  • Au moins une sorte d'accès Internet (via NAT par exemple)
  • Pour ceux qui ont un accès limité au télégramme - Freegate installé et configuré dans le navigateur, dans certains cas difficiles, avec Symple DNS Crypt
  • Avoir un client de télégramme fonctionnel sur votre téléphone
  • Comprendre les bases - ce qu'est une variable, un tableau, une boucle.

Articles ouverts et lus - Instructions : Comment créer des robots dans Telegram и Bot Telegram pour l'administrateur système

1. Créons un autre robot de test.

Puisque tout le monde le sait déjà et que cela s'est déjà produit, vous pouvez également l'ignorer.Comme indiqué dans l'article ci-dessus - Tout d'abord, un bot pour Telegram - il s'agit toujours d'une application fonctionnant de votre côté et faisant des requêtes à l'API Telegram Bot. De plus, l'API est claire : le bot accède à une URL spécifique avec des paramètres et Telegram répond avec un objet JSON.

Problèmes associés : si, d'une manière inconnue, vous prenez du code d'un objet JSON et l'envoyez d'une manière ou d'une autre pour exécution (pas volontairement), le code sera exécuté pour vous.

Le processus de création est décrit dans deux articles ci-dessus, mais je le répète : dans un télégramme, nous ouvrons des contacts, cherchons @botfather, disons-lui /newbot, créons un bot Botfortest12344321, appelons-le Mynext1234bot et recevons un message avec une clé unique du formulaire 1234544311:AbcDefNNNNNNNNNNNNNN

Prenez soin de la clé et ne la donnez pas !

Ensuite, vous pouvez configurer le bot, par exemple, interdire son ajout à des groupes, mais dans les premières étapes, cela n'est pas nécessaire.

Demandons à BotFather « /mybot » et ajustons les paramètres si nous n'aimons pas quelque chose.

Ouvrons à nouveau les contacts, trouvons-y @Botfortest12344321 (il est obligatoire de lancer la recherche avec @), cliquez sur « démarrer » et écrivez au bot « /Gloire aux robots ». Le signe / est obligatoire, les guillemets ne sont pas nécessaires.
Bien entendu, le bot ne répondra à rien.

Vérifions que le bot a été créé et ouvrons-le.

api.telegram.org/bot1234544311:AbcDefNNNNNNNNNNNNNN/getMe
où 1234544311:AbcDefNNNNNNNNNNNNNN est la clé précédemment reçue,
et obtenez une ligne comme
{"ok":vrai,"résultat":{""}}

Nous avons la première phrase secrète (jeton). Nous devons maintenant découvrir le deuxième numéro secret - l'ID du chat avec le bot. Chaque chat, groupe, etc. est individuel et possède son propre numéro (parfois avec un moins - pour les groupes ouverts). Pour connaître ce numéro, nous devons demander dans le navigateur (en fait, ce n'est pas du tout nécessaire dans le navigateur, mais pour une meilleure compréhension vous pouvez commencer par celui-ci) l'adresse (où 1234544311:NNNNNNNNNN est votre token

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

et obtenez une réponse comme

{"ok":true,"result":[{"update_id":...,... le chat":{"identifiant":123456789

Nous avons besoin de chat_id.

Vérifions que nous pouvons écrire manuellement sur le chat : appelez l'adresse depuis le navigateur

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

Si vous recevez un message d’un bot dans votre chat, ok, vous passez à l’étape suivante.

De cette façon (via le navigateur), vous pouvez toujours vérifier s'il y a des problèmes avec la génération du lien ou si quelque chose est caché quelque part et ne fonctionne pas.

Ce qu'il faut savoir avant de continuer la lecture

Telegram propose plusieurs types de discussions de groupe (ouvertes, fermées). Pour ces chats, certaines fonctions (par exemple, id) sont différentes, ce qui pose parfois quelques problèmes.

Supposons que nous soyons fin 2019, et même le héros de notre temps, le célèbre Man-Orchestra (administrateur, avocat, spécialiste de la sécurité de l'information, programmeur et pratiquement MVP) Evgeniy V. distingue la variable $i d'un tableau, a maîtrisé les boucles, regarde dans les prochaines années, il maîtrisera Chocolatey, et ensuite Traitement parallèle avec PowerShell и Parallèle ForEach-Object ça viendra.

1. Nous réfléchissons à ce que fera notre bot

Je n’avais aucune idée, je devais réfléchir. J'ai déjà écrit un bot-notebook. Je ne voulais pas créer un bot « qui envoie quelque chose quelque part ». Pour vous connecter à Azure, vous avez besoin d’une carte de crédit, mais d’où l’étudiant l’obtient-il ? A noter que tout n'est pas si mal : les principaux cloud offrent une sorte de période de test gratuite (mais vous avez toujours besoin d'un numéro de carte de crédit - et il semble qu'un dollar en sera débité. Je ne me souviens pas si il a été rendu plus tard.)

Sans AI ML, ce n'est pas si intéressant de créer un bot-pauvre-poète-tisserand.

J'ai décidé de créer un bot qui me rappellera (ou pas) des mots anglais du dictionnaire.
Pour éviter de manipuler la base de données, le dictionnaire sera stocké dans un fichier texte et mis à jour manuellement.
Dans ce cas, la tâche est de montrer les bases du travail et non de réaliser au moins un produit partiellement fini.

2. Essayer quoi et comment pour la première fois

Créons un dossier C:poshtranslate
Tout d'abord, voyons quel type de PowerShell nous avons, lançons ISE via start-run
powershell ise
ou recherchez Powershell ISE dans les programmes installés.
Après le lancement, l'habituel "une sorte d'éditeur" s'ouvrira ; s'il n'y a pas de champ de texte, vous pouvez toujours cliquer sur "Fichier - créer un nouveau".

Regardons la version de PowerShell - écrivez dans le champ de texte :

get-host 

et appuyez sur F5.

Powershell proposera de sauvegarder - "Le script que vous êtes sur le point d'exécuter sera enregistré.", nous sommes d'accord, et enregistrez le fichier depuis PowerShell avec le nom en C: poshtranslate myfirstbotBT100.

Après le lancement, dans la fenêtre de texte inférieure, nous obtenons un tableau de données :

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

J'ai 5.1 quelque chose, ça suffit. Si vous possédez un ancien Windows 7/8, ce n'est pas grave - même si PowerShell devra être mis à jour vers la version 5 - par ex. instructions.

Tapez Get-Date dans la ligne de commande ci-dessous, appuyez sur Entrée, regardez l'heure, accédez au dossier racine avec la commande
cd
et effacez l'écran avec la commande cls (non, vous n'avez pas besoin d'utiliser rm)

Voyons maintenant ce qui fonctionne et comment - écrivons même pas le code, mais deux lignes, et essayons de comprendre ce qu'ils font. Commentons la ligne avec get-host avec le symbole # et ajoutons-en un peu.

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

(Ce qui est intéressant, c'est que dans la liste déroulante de formatage du code sur Habré, il y a deux douzaines d'options - mais Powershell n'est pas là. Dos est là. Perl est là.)

Et exécutons le code en appuyant sur F5 ou ">" depuis l'interface graphique.

Nous obtenons le résultat suivant :

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

Regardons maintenant ces deux lignes et quelques points intéressants pour ne pas y revenir dans le futur.

Contrairement à Pascal (et pas seulement), PowerShell lui-même essaie de déterminer quel type attribuer à une variable ; plus de détails à ce sujet sont écrits dans l'article Programme éducatif sur la saisie dans les langages de programmation
Par conséquent, en créant une variable $TimeNow et en lui attribuant la valeur de la date et de l'heure actuelles (Get-Date), nous n'avons pas trop à nous soucier du type de données qui s'y trouveront.

Il est vrai que cette ignorance peut faire mal plus tard, mais c’est pour plus tard. Ci-dessous dans le texte, il y aura un exemple.
Voyons ce que nous avons. Exécutons (sur la ligne de commande)

$TimeNow | Get-member

et obtenez une page de texte incompréhensible

Exemple de texte incompréhensible numéro 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")...                                         

Comme vous pouvez le voir, une variable de type TypeName : System.DateTime a été créée avec un tas de méthodes (au sens de ce que l'on peut faire avec cet objet variable) et de propriétés.

Appelons $TimeNow.DayOfYear — nous obtenons le numéro du jour de l'année.
Appelons $TimeNow.DayOfYear | Get-Member - obtenir TypeName: System.Int32 et un groupe de méthodes.
Appelons $TimeNow.ToUniversalTime() - et obtenez l'heure en UTC

Débogueur

Il arrive parfois qu'il soit nécessaire d'exécuter un programme jusqu'à une certaine ligne et de voir l'état du programme à ce moment-là. À cet effet, ISE dispose d'une fonction Debug - basculer le point d'arrêt
Placez un point d'arrêt quelque part au milieu, exécutez ces deux lignes et voyez à quoi ressemble la rupture.

3. Comprendre l'interaction avec le bot Telegram

Bien sûr, encore plus de littérature a été écrite sur l'interaction avec le bot, avec tout getpush, etc., mais la question théorique peut être envisagée facultativement.

Dans notre cas il faut :

  • Apprenez à envoyer quelque chose par correspondance
  • Apprenez à obtenir quelque chose de la correspondance

3.1 Apprendre à envoyer quelque chose par correspondance et à en recevoir

Un peu de code - partie 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

et dans la Fédération de Russie, à ce stade, nous obtenons l'erreur Impossible de se connecter au serveur distant.

Ou nous ne le recevons pas - cela dépend de l'opérateur télécom et si le proxy est configuré et fonctionne
Eh bien, il ne reste plus qu'à ajouter un proxy. Attention, utiliser un proxy non crypté et généralement frauduleux est extrêmement dangereux pour votre santé.

La tâche consistant à trouver un proxy fonctionnel n'est pas très difficile - la plupart des proxys http publiés fonctionnent. Je pense que le cinquième a fonctionné pour moi.

Syntaxe utilisant un proxy :

Invoke-WebRequest -Uri $URL4SEND -Proxy $MyProxy

Si vous recevez un message dans votre chat avec un bot, alors tout va bien, vous pouvez passer à autre chose. Sinon, continuez le débogage.

Vous pouvez voir en quoi se transforme votre chaîne $URL4SEND et essayer de la demander dans le navigateur, comme ceci :

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

3.2. Nous avons appris à écrire « quelque chose » dans le chat, essayons maintenant de le lire

Ajoutons 4 lignes supplémentaires et voyons ce qu'il y a à l'intérieur | devenir membre

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

La chose la plus intéressante nous est fournie

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

Voyons ce qu'il y a dedans :

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

Si tout fonctionne pour vous, vous obtiendrez une longue file d'attente comme :

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

Heureusement, dans l'article Bot Telegram précédemment publié pour l'administrateur système, cette ligne (oui, selon $MyMessageGet.RawContent | get-member est System.String), a déjà été démonté.

4. Traitez ce que vous recevez (nous savons déjà comment envoyer quelque chose)

Comme déjà écrit ici, les choses les plus nécessaires résident dans le contenu. Regardons-le de plus près.

Tout d'abord, nous allons écrire quelques phrases supplémentaires au bot depuis l'interface Web ou depuis le téléphone.

/message1
/message2
/message3

et regardez dans le navigateur l'adresse qui a été formée dans la variable $URLGET.

Nous verrons quelque chose comme :

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

Ce que c'est? Un objet complexe à partir de tableaux d'objets contenant un identifiant de message de bout en bout, un identifiant de chat, un identifiant d'envoi et de nombreuses autres informations.

Cependant, nous n'avons pas besoin de déterminer « de quel type d'objet il s'agit » - une partie du travail a déjà été faite pour nous. Voyons ce qu'il y a à l'intérieur :

Lecture des messages reçus ou partie 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. Que devons-nous faire maintenant ?

Sauvons le fichier résultant sous le nom myfirstbotBT105 ou celui que vous préférez, changeons le titre et commentons tout le code déjà écrit via

<#start comment 105 end comment 105#>

Nous devons maintenant décider où trouver le dictionnaire (enfin, où - sur le disque dans un fichier) et à quoi il ressemblera.

Bien sûr, vous pouvez écrire un énorme dictionnaire directement dans le texte du script, mais cela est complètement hors de propos.
Voyons donc avec quoi PowerShell peut fonctionner normalement.
En général, peu lui importe avec quel fichier travailler, cela n'a pas d'importance pour nous.
Nous avons le choix : txt (vous pouvez, mais pourquoi), csv, xml.
On peut surveiller tout le monde ?
Créons une classe MyVocabClassExample1 et une variable $MyVocabExample1
Je remarque que la classe est écrite sans $

un peu de code #5

write-host "This is part 5"
class MyVocabClassExample1 {
    [string]$Original  # слово
    [string]$Transcript
    [string]$Translate
    [string]$Example
    [int]$VocWordID # очень интересный момент. Использование int с его ограничениями может порой приводить к диким последствиям, для примера - недавний случай с SSD HPE. Изначально я не стал добавлять этот элемент, потом все же дописал и закомментировал.
    }

$MyVocabExample1 = [MyVocabClassExample1]::new()
$MyVocabExample1.Original = "Apple"
$MyVocabExample1.Transcript = "[ ˈapəl ]"
$MyVocabExample1.Translate = "Яблоко"
$MyVocabExample1.Example = "An apple is a sweet, edible fruit produced by an apple tree (Malus domestica)"
# $MyVocabExample1.$VocWordID = 1

$MyVocabExample2 = [MyVocabClassExample1]::new()
$MyVocabExample2.Original = "Pear"
$MyVocabExample2.Transcript = "[ pe(ə)r ]"
$MyVocabExample2.Translate = "Груша"
$MyVocabExample2.Example = "The pear (/ˈpɛər/) tree and shrub are a species of genus Pyrus"
# $MyVocabExample1.$VocWordID = 2

Essayons d'écrire ceci dans des fichiers en utilisant exemplaire.

Un peu de code #5.1

Write-Host $ScriptDir # надеюсь $ScriptDir вы не закомментировали 
$MyFilenameExample01 = $ScriptDir + "Example01.txt"
$MyFilenameExample02 = $ScriptDir + "Example02.txt"
Write-Host $MyFilenameExample01
Out-File  -FilePath $MyFilenameExample01 -InputObject $MyVocabExample1

Out-File  -FilePath $MyFilenameExample01 -InputObject -Append $MyVocabExample2
notepad $MyFilenameExample01

- et on obtient une erreur sur la ligne Out-File -FilePath $MyFilenameExample01 -InputObject -Append $MyVocabExample2.

Il ne veut pas ajouter, ah-ah, quelle honte.

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

Voyons ce qui se passe. Superbe affichage du texte - mais comment le réexporter ? Dois-je introduire des séparateurs de texte, tels que des virgules ?

Et au final vous obtenez un « fichier CSV de valeurs séparées par des virgules » A ARRÊTER D'ATTENDRE.
#

$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 

Comme il est facile de le constater, MS ne se distingue pas particulièrement par sa logique : pour une procédure similaire, dans un cas -FilePath est utilisé, dans un autre -Path.

De plus, dans le troisième fichier, la langue russe a disparu, dans le quatrième fichier, il s'est avéré... eh bien, quelque chose s'est passé. #TYPE Système.Object[] 00
# "Count", "Length", "LongLength", "Rank", "SyncRoot", "IsReadOnly", "IsFixedSize", "IsSynchronized"
#
Réécrivons-le un peu :

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

Cela semble avoir aidé, mais je n’aime toujours pas le format.

Je n'aime particulièrement pas le fait de ne pas pouvoir mettre directement les lignes d'un objet dans un fichier.
Au fait, depuis que nous avons commencé à écrire dans des fichiers, pouvons-nous commencer à tenir un journal de démarrage ? Nous avons le temps comme variable, nous pouvons définir le nom du fichier.

Certes, il n'y a encore rien à écrire, mais vous pouvez réfléchir à la meilleure façon de faire pivoter les journaux.
Essayons XML pour l'instant.

Du 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

L'exportation au format XML présente de nombreux avantages : lisibilité, exportation de l'objet entier et pas besoin d'effectuer une mise à niveau.

Essayons d' lire le fichier XML.

Un peu de lecture de XML

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

Revenons à la tâche. Nous avons écrit un fichier de test, lisons-le, le format de stockage est clair, si nécessaire, vous pouvez écrire un petit éditeur de fichiers séparé pour ajouter et supprimer des lignes.

Permettez-moi de vous rappeler que la tâche était de créer un petit robot d'entraînement.

Format de travail : j'envoie la commande « exemple » au bot, le bot m'envoie un mot et une transcription sélectionnés au hasard, et au bout de 10 secondes m'envoie une traduction et un commentaire. Nous savons lire les commandes, nous aimerions également apprendre à sélectionner et vérifier automatiquement les proxys et à remettre les compteurs de messages dans l'oubli.

Décommentons tout ce qui a été commenté comme inutile, commentons les exemples désormais inutiles avec txt et csv, et enregistrons le fichier sous la version B106.

Oh oui. Envoyons à nouveau quelque chose au bot.

6. Expédition depuis les fonctions et plus encore

Avant de traiter la réception, vous devez créer une fonction permettant d'envoyer « au moins quelque chose » autre qu'un message test.

Bien sûr, dans l’exemple nous n’aurons qu’un seul envoi et un seul traitement, mais que se passe-t-il si nous devons faire plusieurs fois la même chose ?

Il est plus facile d'écrire une fonction. Nous avons donc une variable de type objet $MyVocabExample4AsArray, lue à partir du fichier, sous la forme d'un tableau comprenant jusqu'à deux éléments.
Allons lire.

En même temps, nous nous occuperons de l'horloge ; nous en aurons besoin plus tard (en fait, dans cet exemple, nous n'en aurons pas besoin :)

Un peu de code #6.1

Write-Output "This is Part 6"
$Timezone = (Get-TimeZone)
IF($Timezone.SupportsDaylightSavingTime -eq $True){
    $TimeAdjust =  ($Timezone.BaseUtcOffset.TotalSeconds + 3600) } # приведенное время
    ELSE{$TimeAdjust = ($Timezone.BaseUtcOffset.TotalSeconds) 
    }
    
function MyFirstFunction($SomeExampleForFunction1){
$TimeNow = Get-Date
$TimeNow.ToUniversalTime()
# $MyText02 = $TimeNow + " " + $SomeExampleForFunction1 # и вот тут мы получим ошибку
$MyText02 = $SomeExampleForFunction1 + " " + $TimeNow # а тут не получим, кто догадается почему - тот молодец.

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

Comme vous pouvez facilement le constater, la fonction appelle $MyToken et $MyChatID, qui ont été codés en dur précédemment.

Il n'est pas nécessaire de le faire, et si $MyToken est un pour chaque bot, alors $MyChatID changera en fonction du chat.

Cependant, puisqu’il s’agit d’un exemple, nous l’ignorerons pour l’instant.

Puisque $MyVocabExample4AsArray n'est pas un tableau, bien qu'il en soit très similaire, alors tu ne peux pas le prendre demander sa longueur.

Une fois de plus, nous devrons faire quelque chose qui ne peut pas être fait - parachuter non selon le code - prenez-le et comptez

Un peu de code #6.2

$MaxRandomExample = 0 
foreach ($Obj in $MyVocabExample4AsArray) {
$MaxRandomExample ++
}
Write-Output $MaxRandomExample
$RandomExample = Get-Random -Minimum 0 -Maximum ($MaxRandomExample)
$TextForExample1 = $MyVocabExample4AsArray[$RandomExample].Original
# MyFirstFunction($TextForExample1)
# или в одну строку
# MyFirstFunction($MyVocabExample4AsArray[Get-Random -Minimum 0 -Maximum ($MaxRandomExample -1)].Example)
# Угадайте сами, какой пример легче читается посторонними людьми.

aléatoire fonctionnalité intéressante. Disons que nous voulons recevoir 0 ou 1 (nous n'avons que deux éléments dans le tableau). En fixant les limites 0..1, obtiendrons-nous « 1 » ?
non - nous ne l'obtiendrons pas, nous avons un exemple spécial Exemple 2 : Obtenez un entier aléatoire entre 0 et 99 Get-Random -Maximum 100
Par conséquent, pour 0..1, nous devons définir la taille 0..2, avec le nombre maximum d'éléments = 1.

7. Traitement des messages entrants et longueur maximale de la file d'attente

Où nous sommes-nous arrêtés plus tôt ? nous avons la variable reçue $MyMessageGet
et $Content4Pars01 obtenu à partir de celui-ci, dont nous nous intéressons aux éléments du tableau Content4Pars01.result

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

Envoyons le bot /message10, /message11, /message12, /word et encore /word et /hello.
Voyons ce que nous avons obtenu :

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

Passons en revue tout ce qui a été reçu et envoyons une réponse si le message était /word
le cas de construction, ce que certains décrivent comme if-elseif, est appelé en PowerShell via un interrupteur. Dans le même temps, le code ci-dessous utilise la clé -wildcard, ce qui est totalement inutile et même nuisible.

Un peu de code #7.1

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

Exécutons le script plusieurs fois. Nous obtiendrons le même mot deux fois à chaque tentative d'exécution, surtout si nous avons commis une erreur dans la mise en œuvre du hasard.

Mais arrêtez. Nous n’avons plus envoyé /word, alors pourquoi le message est-il à nouveau traité ?

La file d'attente pour envoyer des messages au bot a une longueur finie (100 ou 200 messages, je pense) et doit être vidée manuellement.

Ceci est bien sûr décrit dans la documentation, mais il faut la lire !

Dans ce cas, nous avons besoin du paramètre ?chat_id, et &timeout, &limit, &parse_mode=HTML et &disable_web_page_preview=true ne sont pas encore nécessaires.

Documentation pour L'API du télégramme est ici
Il est écrit en blanc et en anglais :
Identifiant de la première mise à jour à retourner. Doit être supérieur d’un au plus élevé parmi les identifiants des mises à jour précédemment reçues. Par défaut, les mises à jour commencent par la première
non confirmé la mise à jour est renvoyée. Une mise à jour est considérée comme confirmée dès que getUpdates est appelé avec un compenser augmentation que son update_id. Le décalage négatif peut être spécifié pour récupérer les mises à jour à partir de -offset update à partir de la fin de la file d'attente des mises à jour. Toutes les mises à jour précédentes seront oubliées.

Regardons:

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

Oui, et nous allons le réinitialiser et réécrire un peu la fonction. Nous avons deux options : transmettre l'intégralité du message à la fonction et le traiter entièrement dans la fonction, ou donner uniquement l'ID du message et le réinitialiser. Par exemple, le second semble plus simple.

Auparavant, notre chaîne de requête « tous les messages » ressemblait à

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

et ça ressemblera à

$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 

Personne ne vous interdit de recevoir d'abord tous les messages, de les traiter, et seulement après traitement réussi demande non confirmée -> confirmée.

Pourquoi est-il judicieux d’appeler pour confirmer une fois tous les traitements terminés ? Un échec est possible en cours d’exécution, et si pour l’exemple d’un chatbot gratuit, manquer un seul message n’a rien de spécial, alors si vous traitez le salaire ou la transaction par carte de quelqu’un, le résultat peut être pire.

Quelques lignes de code supplémentaires

$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. Au lieu d'une conclusion

Les fonctions de base - lecture des messages, réinitialisation de la file d'attente, lecture à partir d'un fichier et écriture dans un fichier sont effectuées et affichées.

Il ne reste plus que quatre choses à faire :

  • envoyer la bonne réponse à une demande dans le chat
  • envoyer une réponse à TOUT chat auquel le bot a été ajouté
  • exécuter du code en boucle
  • lancer un bot depuis le planificateur Windows.

Toutes ces tâches sont simples et peuvent être facilement accomplies en lisant la documentation sur les paramètres tels que
Set-ExecutionPolicy Unrestricted et -ExecutionPolicy Bypass
cycle de la forme

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

Merci à tous d'avoir lu.

Source: habr.com

Ajouter un commentaire