Modèle de robot Telegram pour les élèves de 7e à 9e année en Powershell

Lors d'une conversation avec un ami, j'ai soudainement découvert que les enfants en classe de 8-10 dans leur école n'apprenaient pas du tout la programmation. Juste Word, Excel et c'est tout. Ni Logo, ni même Pascal, ni même VBA pour Excel.

J'ai été très surpris, j'ai ouvert internet et je me suis mis à lire —
L'un des objectifs d'une école spécialisée est de contribuer à la formation d'une nouvelle génération, correspondant par son niveau de développement et son mode de vie aux conditions de la société de l'information.
Ce cours permettra de consolider en pratique les connaissances des élèves sur les constructions de base du langage de programmation Pascal. (extrait d'un programme d'un certain lycée de 2017)

Au final, j'ai décidé de passer quelques heures à esquisser un exemple de « comment créer un simple bot — pour les élèves ».

Sous ce lien, comment écrire un simple bot en Powershell et le faire fonctionner sans webhook, IP publiques, serveurs dédiés, machines virtuelles déployées dans le cloud, etc. — sur un PC domestique ordinaire avec Windows ordinaire.

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

L'article n'apporte rien de nouveau, presque tout ce qui est écrit a déjà été traité sur Habr, par exemple dans les articles Instruction : Comment créer des bots dans Telegram et Bot Telegram pour administrateurs système.
De plus, l'article est délibérément excessif pour éviter de renvoyer chaque fois à la littérature pédagogique. Aucune référence à la bande 4, aux PowerShell Deep Dives ou à la chaîne The 5 Pillars of the AWS Well-Architected Framework dans le texte.

Au lieu d'une préface, on peut passer

On passe sans hésiterEn 2006, Microsoft a sorti PowerShell 1.0 pour ce qui était alors Windows XP, Vista et Windows Server 2003. D'une certaine manière, il a remplacé des éléments tels que les scripts cmd, les scripts vb, Windows Script Host et JScript.

Même aujourd'hui, PowerShell ne peut être considéré que comme une étape supplémentaire après les variantes de Logo, bien qu'il contienne des boucles, des classes, des fonctions, et l'appel de l'interface graphique de Windows, malgré que Delphi (ou des technologies plus anciennes) soit encore peut-être utilisé. Intégration avec Git et ainsi de suite.

PowerShell est relativement rarement utilisé, on ne peut le rencontrer que sous la forme de PowerShell Core, VMware vSphere PowerCLI, Azure PowerShell, MS Exchange, Desired State Configuration, PowerShell Web Access et une dizaine d'autres programmes et fonctions peu utilisés. Peut-être qu'il connaîtra un second souffle avec la sortie de WSL2, mais ce n'est pas certain.

PowerShell a aussi trois grands avantages :

  1. Il est relativement simple, il existe beaucoup de littérature et d'exemples à son sujet, même en russe, par exemple un article sur Foreach — tiré d'un livre PowerShell en profondeur — concernant la différence entre () et {}
  2. Il est livré avec l'éditeur ISE, inclus avec Windows. Il y a même un débogueur.
  3. Il permet d'appeler facilement des composants pour construire une interface graphique.

0. Préparation.

Nous aurons besoin de :

  • Un PC avec Windows (j'ai Windows 10)
  • Une connexion Internet de toute sorte (via NAT par exemple)
  • Pour ceux qui ont un accès limité à Telegram — un freegate installé et configuré dans le navigateur, dans certains cas complexes conjointement avec Symple DNS Crypt
  • La présence d'un client Telegram fonctionnel sur le téléphone
  • Compréhension des bases — qu'est-ce qu'une variable, un tableau, une boucle.

Articles ouverts et lus — Instruction : Comment créer des bots dans Telegram et Bot Telegram pour administrateurs système

1. Créons un nouveau bot de test.

Puisque tout le monde le sait déjà et que cela a été abordé, nous pouvons aussi le sauterComme mentionné dans l'article ci-dessus — Avant tout, un bot pour Telegram — c'est toujours une application qui s'exécute de votre côté et effectue des demandes à l'API Telegram Bot. De plus, l'API est claire — le bot fait appel à une URL spécifique avec des paramètres, et Telegram répond avec un objet JSON.

Les problèmes y afférents : si d'une manière ou d'une autre, vous prenez un certain code d'un objet JSON et l'envoyez à l'exécution (involontairement) — le code s'exécutera chez vous.

Le processus de création est décrit dans les deux articles ci-dessus, mais je répète : dans Telegram, ouvrez les contacts, recherchez @botfather, dites-lui /newbot, créons le bot Botfortest12344321, nommons-le Mynext1234bot, et nous recevrons un message avec une clé unique du type 1234544311:AbcDefNNNNNNNNNNNNN

Gardez bien la clé et ne la partagez pas !

Ensuite, vous pouvez configurer le bot, par exemple interdire son ajout dans des groupes, mais au début, ce n'est pas nécessaire.

Demandons à BotFather «/mybot» et modifions les paramètres si quelque chose ne convient pas.

Nous ouvrirons à nouveau les contacts, y chercherons @Botfortest12344321 (commencer la recherche avec @ est obligatoire), appuierons sur «démarrer» et écrirons au bot «/Gloire aux robots». Le signe / est obligatoire, les guillemets ne sont pas nécessaires.
Le bot, bien sûr, ne répondra pas.

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

api.telegram.org/bot1234544311:AbcDefNNNNNNNNNNNNN/getMe
où 1234544311:AbcDefNNNNNNNNNNNNN — la clé précédemment obtenue,
et nous obtiendrons une chaîne de type
{«ok»:true,«result»:{«»}}

Nous avons la première phrase secrète (token). Maintenant, nous devons connaître le deuxième numéro secret - l'ID du chat avec le bot. Chaque chat, groupe, etc. est unique et a son propre numéro (parfois avec un signe moins - pour les groupes ouverts). Pour connaître ce numéro, nous devons demander dans le navigateur (en réalité, ce n'est pas forcément dans le navigateur, mais pour mieux comprendre, on peut commencer par ça) l'adresse (où 1234544311:NNNNNNNNN est votre token

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

et obtenir une réponse de type

{«ok»:true,«result»:[{«update_id»:…,… chat«:{«id»:123456789

Nous avons besoin précisément du chat_id.

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

https://api.telegram.org/botvotretoken/sendMessage?chat_id=123456789&text="Life is directed motion"

Si un message du bot arrive dans votre chat - d'accord, vous passez à l'étape suivante.

Ainsi (via le navigateur), vous pouvez toujours vérifier où se trouvent les problèmes - lors de la génération du lien, ou quelque chose est caché et ne fonctionne pas.

Ce qu'il faut savoir avant de continuer la lecture

Dans Telegram, il existe plusieurs types de chats de groupe (ouverts, fermés). Pour ces chats, certaines fonctions (par exemple, l'id) diffèrent, ce qui peut parfois poser des problèmes.

Considérons que nous sommes à la fin de l'année 2019, et même le héros de notre temps, le célèbre Homme-Orchestre (administrateur, juriste, expert en sécurité de l'information, programmeur et pratiquement MVP) Evgueni V. distingue la variable $i d'un tableau, a maîtrisé les boucles, espérons qu'il maîtrisera Chocolatey dans les prochaines années, et puis le traitement parallèle avec PowerShell et ForEach-Object Parallel sera atteint.

1. Réfléchissons à ce que fera notre bot

Je n'avais pas d'idées, j'ai dû réfléchir. J'avais déjà écrit un bot de prise de notes. Je ne voulais pas faire un bot « qui transfère quelque chose quelque part ». Pour se connecter à Azure, il faut une carte de crédit, et d'où cela vient-il pour un collégien ? Il faut noter que ce n'est pas si mal : les principaux clouds offrent un certain période d'essai gratuitement (mais un numéro de carte est toujours nécessaire - et un dollar sera facturé, semble-t-il. Je ne me souviens pas s'il a été remboursé ensuite.)

Sans IA, faire un bot de poète pas si intéressant.

J'ai décidé de faire un bot qui me rappellera (ou pas) des mots anglais du dictionnaire.
Le dictionnaire, pour ne pas avoir à manipuler une base de données, sera stocké dans un fichier texte et sera rempli manuellement.
Dans ce cas, l'objectif est de montrer les bases du travail et non de créer un produit prêt à l'emploi.

2. Essayons ce que c'est et comment cela fonctionne pour la première fois

Créons un dossier C:poshtranslate
Pour commencer, voyons ce qu'est notre powershell, lançons ISE via exécuter dans le menu démarrer
powershell ise
ou trouvons Powershell ISE dans les programmes installés.
Après le lancement, un « éditeur quelconque » habituel s'ouvrira, si le champ de texte n'est pas présent, vous pouvez toujours cliquer sur « Fichier - créer nouveau ».

Vérifions la version de powershell - écrivons dans le champ de texte :

get-host 

et appuyons sur F5.

Powershell proposera de sauvegarder - « Le script que vous êtes sur le point d'exécuter sera sauvegardé. », nous acceptons et sauvegardons dans C:poshtranslate le fichier de powershell avec le nom myfirstbotBT100.

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

Nom             : Windows PowerShell ISE Host
Version          : 5.1.(et ainsi de suite)

J'ai 5.1 quelque chose, c'est suffisant. Si vous avez un ancien Windows 7/8, ce n'est pas grave - bien que PowerShell doive être mis à jour vers la version 5 - par exemple, avec des instructions.

Nous allons taper dans la ligne de commande ci-dessous Get-Date, appuyer sur Entrée, vérifier l'heure, retourner dans le dossier racine avec la commande
cd
et nettoyer l'écran avec la commande cls (non, il ne faut pas utiliser rm)

Maintenant, vérifions comment cela fonctionne - nous allons écrire non pas du code, mais deux lignes, et essayer de comprendre ce qu'elles font. Nous commenterons la ligne avec get-host avec le symbole # et écrirons un peu plus.

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

(Ce qui est intéressant. Dans la liste déroulante des formats de code sur Habr, il y a une vingtaine d'options — mais powershell n'est pas là. Dos est là. Perl est là.)

Et nous lancerons le code, en appuyant sur F5 ou « > » depuis l'interface graphique.

Nous obtiendrons la sortie :

Samedi 8 décembre 2019 21:00:50 PM (ou quelque chose de ce genre)

Maintenant, examinons ces deux lignes et certains points intéressants afin de ne pas revenir à cela plus tard.

Contrairement à Pascal (et pas seulement), PowerShell essaie lui-même de définir quel type attribuer à une variable, plus de détails sont écrits dans l'article Guide de typage dans les langages de programmation
Donc, en créant la variable $TimeNow et en lui attribuant la valeur de la date et de l'heure actuelles (Get-Date), nous n'avons pas à nous soucier des types de données qui y seront.

Cependant, ce manque de connaissance peut causer des douleurs plus tard, mais c'est plus tard. Un exemple sera donné plus bas dans le texte.
Voyons ce que nous avons obtenu. Exécutons (dans la ligne de commande)

$TimeNow | Get-member

et nous obtiendrons une page de texte incompréhensible

Exemple de texte incompréhensible numéro 1

PS C:&gt; $TimeNow | Get-member
   TypeName: System.DateTime
Nom                 TypeMembre     Définition                                                                                                                                       
----                 ----------     ----------                                                                                                                                       
Ajouter                  <b>Méthode         </b>datetime Ajouter(timespan valeur)  
..
IndicationAffichage          NotePropriété   TypeIndicationAffichage IndicationAffichage=DateTime                                                                                                             
Date                 <b>Propriété       </b>datetime Date {get;}                                                                                                                             
Année                 Propriété       int Année {get;}   
..                                                                                                                               
DateTime             ScriptPropriété System.Object DateTime {get=if ((&amp; { Set-StrictMode -Version 1; $this.IndicationAffichage }) -ieq  "Date")...                                         

Comme nous pouvons le voir, une variable de type TypeName : System.DateTime a été créée avec une multitude de méthodes (dans le sens, ce que nous pouvons faire avec cet objet-variable) et de propriétés.

Nous appellerons $TimeNow.DayOfYear — nous allons obtenir le numéro du jour dans l'année.
Nous appellerons $TimeNow.DayOfYear | Get-Member — nous allons obtenir TypeName: System.Int32 et un groupe de méthodes.
Nous appellerons $TimeNow.ToUniversalTime() — et nous obtiendrons 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 vérifier l'état du programme à ce moment-là. Pour cela, l'ISE a une fonction Débogage — activer le point d'arrêt.
Placez un point d'arrêt quelque part au milieu, exécutez ces deux lignes et regardez à quoi ressemble l'arrêt.

3. Comprendre l'interaction avec le bot Telegram

Bien sûr, il existe encore plus de littérature sur l'interaction avec le bot, sur tous les getpush, etc., cependant, la question de la théorie peut être examinée en option.

Dans notre cas, nous devons :

  • Apprendre à envoyer quelque chose dans la conversation
  • Apprendre à recevoir quelque chose de la conversation

3.1 Apprenons à envoyer quelque chose dans la conversation et à le recevoir

Un peu de code — partie 3

Write-output "C'est la partie 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 = "La vie est un mouvement dirigé - " + $TimeNow

$URL4SEND = "https://api.telegram.org/bot$MyToken/sendMessage?chat_id=$MyChatID&text=$MyText01"

Invoke-WebRequest -Uri $URL4SEND

et en RF, à cet endroit, nous obtenons l'erreur Impossible de se connecter au serveur distant.

Ou nous ne l'obtenons pas — cela dépend de l'opérateur mobile et de la manière dont le proxy est configuré et fonctionne.
Eh bien, il reste à ajouter un proxy. Notez que l'utilisation d'un proxy non chiffré et complètement aléatoire est extrêmement dangereuse pour votre santé.

La tâche de trouver un proxy fonctionnel n'est pas très difficile — la plupart des proxies http publiés fonctionnent. Il m'a semblé que le cinquième à la suite a fonctionné.

Syntaxe utilisant un proxy :

Invoke-WebRequest -Uri $URL4SEND -Proxy $MyProxy

Si vous avez reçu un message dans votre chat avec le bot — c'est parfait, vous pouvez continuer. Sinon, poursuivez le débogage.

Vous pouvez voir à quoi ressemble votre chaîne $URL4SEND et essayer de la demander dans le navigateur, par exemple comme ceci :

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

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

Ajoutons encore 4 lignes et voyons ce qu'il y a à l'intérieur via | get-member

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

Ce qui est le plus intéressant nous est fourni par

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

Voyons ce qu'il y a à l'intérieur :

Write-Host "ParsedHtml"
$MyMessageGet.ParsedHtml # ici c'est intéressant
Write-Host "RawContent"
$MyMessageGet.RawContent # et ici aussi c'est intéressant, mais en plus c'est lisible. 
Write-Host "Content"
$MyMessageGet.Content

Si tout fonctionne, vous obtiendrez une longue chaîne de type :

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

Heureusement, dans un article précédent sur le bot Telegram pour administrateurs système, cette ligne (oui, selon $MyMessageGet.RawContent | get-member — c'est un System.String), a déjà été analysée.

4. Traiter ce qui a été reçu (nous savons déjà comment envoyer quelque chose)

Comme déjà écrit ici, le plus nécessaire est dans le content. Regardons-le de plus près.

D'abord, écrivons quelques phrases au bot depuis l'interface web ou le téléphone

/message1
/message2
/message3

et regardons 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 

Qu'est-ce que c'est ? Un objet compliqué d'arrays d'objets, contenant un identifiant de message, un identifiant de chat, un identifiant d'envoi et plein d'autres informations.

Cependant, nous n'avons pas besoin d'analyser « ce qu'est cet objet » — une partie du travail a déjà été faite pour nous. Regardons ce qu'il y a à l'intérieur :

Nous lisons les 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 avec cela

Enregistrons le fichier reçu sous le nom myfirstbotBT105 ou comme vous le préférez, changeons le titre et commentons tout le code déjà écrit avec

<#start comment 105 end comment 105#>

Maintenant, nous devons déterminer où obtenir le dictionnaire (en fait, où — sur le disque dans un fichier) et à quoi il ressemblera.

Bien sûr, on pourrait remplir un énorme dictionnaire directement dans le texte du script, mais ce n'est pas l'idéal.
Donc, voyons avec quoi PowerShell fonctionne effectivement.
En fait, il lui est égal avec quel fichier travailler, mais pas à nous.
Nous avons le choix entre : txt (ça marche, mais pourquoi), csv, xml.
Ou nous pouvons tous les voir. Regardons tous.
Créons la classe MyVocabClassExample1 et la variable $MyVocabExample1
je note que la classe s'écrit sans $

un peu de code #5

write-host "Ceci est la partie 5"
class MyVocabClassExample1 {
    [string]$Original  # mot
    [string]$Transcript
    [string]$Translate
    [string]$Example
    [int]$VocWordID # un point très intéressant. L'utilisation de int avec ses limitations peut parfois mener à des conséquences étranges, par exemple - le cas récent avec SSD HPE. Au début, je n'avais pas ajouté cet élément, mais ensuite je l'ai tout de même écrit et commenté.
    }

$MyVocabExample1 = [MyVocabClassExample1]::new()
$MyVocabExample1.Original = "Apple"
$MyVocabExample1.Transcript = "[ ˈapəl ]"
$MyVocabExample1.Translate = "Pomme"
$MyVocabExample1.Example = "Une pomme est un fruit comestible, sucré, produit par un pommier (Malus domestica)"
# $MyVocabExample1.$VocWordID = 1

$MyVocabExample2 = [MyVocabClassExample1]::new()
$MyVocabExample2.Original = "Pear"
$MyVocabExample2.Transcript = "[ pe(ə)r ]"
$MyVocabExample2.Translate = "Poire"
$MyVocabExample2.Example = "Le poirier (/'pɛər/) et les arbustes sont une espèce du genre Pyrus"
# $MyVocabExample1.$VocWordID = 2

Essayons d'enregistrer cela dans des fichiers selon le modèle.

Un peu de code #5.1

Write-Host $ScriptDir # j'espère que vous n'avez pas commenté $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 nous aurons une erreur à la ligne Out-File -FilePath $MyFilenameExample01 -InputObject -Append $MyVocabExample2.

Il ne veut pas ajouter, quelle déception.

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

Voyons ce que cela donne. Un texte clair — mais comment l'exporter à nouveau ? Devons-nous entrer des séparateurs de texte, comme des virgules ?

Et au final obtenir "un fichier à séparateurs — des virgules, des valeurs séparées par des virgules (CSV) A STOP ATTENDEZ.
#

$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 

Il est facile de voir que, MS n'a pas particulièrement fait preuve de logique, pour une procédure similaire dans un cas il utilise -FilePath, pour l'autre -Path.

De plus, dans le troisième fichier le russe a disparu, dans le quatrième fichier il s'est passé… eh bien, quelque chose s'est passé. #TYPE System.Object[] 00
# „Count“,»Length»,«LongLength»,«Rank»,«SyncRoot»,«IsReadOnly»,«IsFixedSize»,«IsSynchronized»
#
Réécrivons 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 le format ne me plaît toujours pas.

Surtout, cela ne me plaît pas que je ne puisse pas mettre les chaînes de l'objet dans le fichier directement.
D'ailleurs, puisque nous avons commencé à écrire dans des fichiers, pourquoi ne pas commencer à tenir un journal de démarrage ? Nous avons le temps comme variable, et nous savons définir le nom du fichier.

Pour l'instant, il n'y a rien à écrire, mais nous pouvons réfléchir à la meilleure manière de gérer la rotation des logs.
Essayons avec xml.

Un peu de 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 en xml a de nombreux avantages — lisibilité, exportation de l'objet entier, et pas besoin d'effectuer d'ajout.

Essayons lire le fichier xml.

Un peu de lecture à partir de xml

$MyFilenameExample06 = $ScriptDir + "Example06.xml"
$MyVocabExample4AsArray = Import-Clixml -Path $MyFilenameExample06
# $MyVocabExample4AsArray 
# $MyVocabExample4AsArray[0]
# et un peu sur des nuances tout à fait inattendues. Powershell se comporte parfois différemment de ce que l'on pourrait attendre.
# par exemple, ces deux sorties diffèrent
# Write-Output $MyVocabExample4AsArray 
# write-host $MyVocabExample4AsArray 

Revenons à la tâche. Nous avons écrit le fichier d'essai, l'avons lu, le format de stockage est clair, et si nécessaire, nous pouvons écrire un petit éditeur pour ajouter et supprimer des lignes.

Je rappelle que la tâche était de créer un petit bot d'apprentissage.

Mode de fonctionnement : j'envoie une commande « exemple » au bot, et le bot m'envoie un mot choisi au hasard avec sa transcription, puis, après 10 secondes, il envoie la traduction et un commentaire. Nous savons traiter les commandes, il faudrait juste apprendre à choisir et vérifier automatiquement des proxy, et à réinitialiser les compteurs de messages.

Décommentons tout ce qui a été commenté comme inutile, commentons les exemples devenus superflus avec txt et csv, et sauvegardons le fichier en tant que version B106.

Ah oui. Envoyons quelque chose au bot encore une fois.

6. Envoi depuis des fonctions et pas seulement

Avant de traiter la réception, nous devons créer une fonction pour envoyer « quelque chose », en dehors du message de test.

Bien sûr, dans notre exemple, il n'y aura qu'un seul envoi et seulement une seule réception, mais que faire si nous devons répéter la même opération plusieurs fois ?

Il est plus simple d'écrire une fonction. Donc, nous avons une variable de type objet $MyVocabExample4AsArray, lue à partir du fichier, sous forme de tableau avec deux éléments.
Allons-y, lisons.

En même temps, nous allons nous pencher sur les heures, cela nous sera utile plus tard (en fait, dans cet exemple, ce ne sera pas utile 🙂

Un peu de code #6.1

Write-Output "Ceci est la partie 6"
$Timezone = (Get-TimeZone)
IF($Timezone.SupportsDaylightSavingTime -eq $True){
    $TimeAdjust =  ($Timezone.BaseUtcOffset.TotalSeconds + 3600) } # heure d'été
    ELSE{$TimeAdjust = ($Timezone.BaseUtcOffset.TotalSeconds) 
    }
    
function MyFirstFunction($SomeExampleForFunction1){
$TimeNow = Get-Date
$TimeNow.ToUniversalTime()
# $MyText02 = $TimeNow + " " + $SomeExampleForFunction1 # et ici nous obtiendrons une erreur
$MyText02 = $SomeExampleForFunction1 + " " + $TimeNow # mais ici nous n'en obtiendrons pas, qui devinera pourquoi - c'est un génie.

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

Comme il est facile de voir, la fonction appelle $MyToken et $MyChatID, qui ont été attribués précédemment.

Ce n'est pas la bonne approche, et si $MyToken est le même pour chaque bot, alors le $MyChatID variera selon le chat.

Cependant, comme c'est un exemple, nous allons l'ignorer pour le moment.

Puisque $MyVocabExample4AsArray n'est pas un tableau, bien qu'il y ressemble beaucoup, il n'est pas possible de juste prendre et demander sa longueur.

Nous devrons encore une fois faire quelque chose que nous ne devrions pas - faire un atterrissage non conforme - prendre et compter

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)
# ou en une seule ligne
# MyFirstFunction($MyVocabExample4AsArray[Get-Random -Minimum 0 -Maximum ($MaxRandomExample -1)].Example)
# Devinez vous-même, quel exemple est le plus lisible pour les personnes extérieures.

Aléatoire fonction intéressante. Supposons que nous voulons obtenir 0 ou 1 (nous avons seulement deux éléments dans le tableau). En définissant les limites 0..1 - obtiendrons-nous «1»?
non - nous n'obtiendrons pas, nous avons spécifiquement présenté l'exemple Example 2 : Obtenir un entier aléatoire entre 0 et 99 Get-Random -Maximum 100
Donc pour 0..1, nous devrons définir la taille de 0..2, avec le numéro maximal de l'élément = 1.

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

Où en étions-nous précédemment ? nous avons obtenu la variable $MyMessageGet
et récupéré $Content4Pars01, dont nous sommes intéressés par les éléments du tableau Content4Pars01.result

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

Nous enverrons au bot /message10, /message11, /message12, /word et encore une fois /word et /salut.
Voyons ce que nous avons reçu :

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

Nous parcourons tout ce que nous avons reçu et envoyons une réponse si le message était /word
la structure case of, ce que certains décrivent comme if-elseif, dans powershell est appelé via switchDans le code ci-dessous, la clé -wildcard est utilisée, ce qui n'est pas nécessaire et même nuisible.

Un peu de code #7.1

Write-Output "Ceci est la partie 7"
Foreach ($Result in $Content4Pars01.result) # Oui, c'est possible de le faire plus rapidement 
 { 
    switch -wildcard ($Result.message.text) 
            {
            "\/word" {MyFirstFunction($TextForExample1)}
            }
}

Exécutons le script quelques fois. Nous obtiendrons le même mot deux fois à chaque exécution, surtout si nous avons fait une erreur dans l'implémentation random.

Mais stop. Nous n'avons pas envoyé \/word encore une fois, pourquoi le message est-il traité à nouveau ?

La file d'attente pour envoyer des messages au bot a une longueur finie (il semble que ce soit 100 ou 200 messages), et elle doit être nettoyée manuellement.

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

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

La documentation sur l'API de telegram se trouve ici
Il est écrit en anglais comme suit :
Identifiant de la première mise à jour à être retournée. Doit être supérieur de un à celui des identifiants des mises à jour précédemment reçues. Par défaut, les mises à jour commençant par la plus ancienne
non confirmée sont retournées. Une mise à jour est considérée comme confirmée dès que getUpdates est appelé avec un offset supérieur à son update_id. Le décalage négatif peut être spécifié pour récupérer les mises à jour en commençant par -offset mise à jour depuis la fin de la file d'attente des mises à jour. Toutes les mises à jour précédentes seront oubliées.

Jetons un œil à :

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

Et réinitialisons — écrivons un peu différemment la fonction. Nous avons deux options — passer le message entier à la fonction et le traiter complètement dans la fonction, ou bien donner uniquement l'ID du message et le réinitialiser également. Pour l'exemple, la seconde option semble plus simple.

Auparavant, notre requête pour « tous les messages » ressemblait à

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

et 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 d'abord obtenir tous les messages, de les traiter, et uniquement après un traitement réussi de demander unconfirmed -> confirmed.

Pourquoi a-t-il du sens d'appeler la confirmation après avoir terminé tous les traitements ? Il pourrait y avoir une défaillance au milieu de l'exécution, et si par exemple pour un chatbot gratuit, sauter un message unique n'est pas si grave, lorsqu'il s'agit de traiter un salaire ou une transaction par carte, le résultat peut être bien pire.

Encore quelques lignes de code

$LastMessageId = ($Content4Pars01.result | select -last 1).update_id  #l'erreur à cet endroit doit être corrigée soi-même. 
$URLGET1 = "https://api.telegram.org/bot$mytoken/getUpdates?offset=$LastMessageId&limit=100" 
Invoke-WebRequest -Uri $URLGET1 -Method Get -Proxy $MyProxy

8. En guise de conclusion

Les fonctionnalités principales — lire les messages, réinitialiser la file d'attente, lire à partir d'un fichier et écrire dans un fichier ont été réalisées et présentées.

Il reste à faire quatre choses au total :

  • envoyer la bonne réponse à la demande dans le chat
  • envoyer une réponse dans N'IMPORTE quel chat dans lequel le bot a été ajouté
  • exécuter le code en boucle
  • lancer le bot à partir du planificateur Windows.

Toutes ces tâches sont simples et facilement réalisables en consultant la documentation sur des paramètres tels que
Set-ExecutionPolicy Unrestricted et -ExecutionPolicy Bypass
une boucle de type

$TimeToSleep = 3 # interrogations toutes les 3 secondes
$TimeToWork = 10 # minutes
$HowManyTimes = $TimeToWork*60/$TimeToSleep # compteur pour la boucle
$MainCounter = 0
for ($MainCounter=0; $MainCounter -le $HowManyTimes) {
sleep $TimeToSleep
$MainCounter ++

Merci à tous ceux qui ont lu jusqu'à la fin.

Source : habr.com

Acheter un hébergement fiable pour les sites avec protection DDoS, serveurs VPS VDS 🔥 Acheter un hébergement fiable pour les sites avec protection DDoS, serveurs VPS VDS | ProHoster