Plantilla para un bot de Telegram simple para escolares de 7.º a 9.º grado usando Powershell

Durante conversaciones con un amigo, de repente me enteré de que a los niños de 8.º a 10.º grado en su escuela no se les enseña programación en absoluto. Word, Excel y todo. Sin logotipo, ni siquiera Pascal, ni siquiera VBA para Excel.

Me sorprendió mucho, abrí Internet y comencé a leer.
Una de las tareas de una escuela especializada es promover la educación de una nueva generación que cumpla con las condiciones de la sociedad de la información en su nivel de desarrollo y estilo de vida.
Este curso permitirá a los estudiantes consolidar en la práctica sus conocimientos de las construcciones básicas del lenguaje de programación Pascal. (del programa de algún gimnasio para 2017)

Al final, decidí dedicar un par de horas y esbozar un ejemplo de "cómo crear un bot simple para escolares".

Debajo del corte se muestra cómo escribir otro bot simple en Powershell y hacer que funcione sin un webhook, IP blancas, servidores dedicados, máquinas virtuales implementadas en la nube, etc., en una PC doméstica normal con Windows normal.

TLDR: Otro artículo aburrido con errores gramaticales y fácticos, nada que leer, sin humor, sin imágenes.

No hay nada nuevo en el artículo, casi todo lo escrito antes ya estaba en Habré, por ejemplo en artículos. Instrucciones: Cómo crear bots en Telegram и Bot de Telegram para administrador del sistema.
Además, el artículo es deliberadamente redundante para no hacer referencia siempre a la literatura educativa. No hay referencias a Gang 4, PowerShell Deep Dives o, digamos, Los 5 pilares del marco de buena arquitectura de AWS en el texto.

En lugar de un prefacio, puedes saltarte

Siéntete libre de saltarEn 2006, Microsoft lanzó PowerShell 1.0 para los entonces Windows XP, Vista y Server 2003. En cierto modo, reemplazó elementos como los scripts cmdbat, los scripts vb, Windows Script Host y JScript.

Incluso ahora, PowerShell solo puede considerarse como el siguiente paso después de las opciones del logotipo, en lugar del Delphi probablemente todavía usado (o algo más antiguo), a pesar de la presencia de bucles, clases, funciones, llamadas de MS GUI, integración de git y así sucesivamente.

Powershell se usa relativamente raramente; solo puede encontrarlo en forma de PowerShell Core, VMware vSphere PowerCLI, Azure PowerShell, MS Exchange, Desired State Configuration, Acceso web a PowerShell y una docena de programas y funciones más poco utilizados. Tal vez obtenga un segundo aire con la liberación. WSL2, pero no es exactamente.

Powershell también tiene tres grandes ventajas:

  1. Es relativamente simple, hay mucha literatura y ejemplos al respecto, e incluso en ruso, por ejemplo, un artículo sobre Foreach, del libro. PowerShell en profundidad - sobre la diferencia () y {}
  2. Él va con el editor. ISE, incluido con Windows. Incluso hay algún tipo de depurador allí.
  3. Es fácil llamar desde allí. Componentes para construir una interfaz gráfica..

0. Preparacion

Vamos a necesitar:

  • PC con Windows (tengo Windows 10)
  • Al menos algún tipo de acceso a Internet (a través de NAT, por ejemplo)
  • Para aquellos que tienen acceso limitado a Telegram: instale y configure freegate en el navegador, en algunos casos difíciles, junto con Symle DNS Crypt
  • Tener un cliente de Telegram que funcione en su teléfono
  • Comprender los conceptos básicos: qué es una variable, una matriz o un bucle.

Artículos abiertos y leídos - Instrucciones: Cómo crear bots en Telegram и Bot de Telegram para administrador del sistema

1. Creemos otro bot de prueba.

Como todo el mundo ya sabe esto y ya ha sucedido, también puedes omitirlo.Como se indica en el artículo anterior: en primer lugar, un bot para Telegram. sigue siendo una aplicación que se ejecuta de su lado y realiza solicitudes a la API de Telegram Bot. Además, la API es clara: el bot accede a una URL específica con parámetros y Telegram responde con un objeto JSON.

Problemas relacionados: si de alguna manera desconocida toma algún código de un objeto JSON y de alguna manera lo envía para su ejecución (no a propósito), el código se ejecutará por usted.

El proceso de creación está descrito en dos artículos anteriores, pero repito: en un telegrama abrimos contactos, buscamos @botfather, le decimos /newbot, creamos un bot Botfortest12344321, lo llamamos Mynext1234bot y recibimos un mensaje con una clave única del formulario 1234544311: AbcDefNNNNNNNNNNNNNNNN

¡Cuida la llave y no la regales!

Luego puedes configurar el bot, por ejemplo, prohibir agregarlo a grupos, pero en los primeros pasos esto no es necesario.

Pidamos a BotFather "/mybot" y ajustemos la configuración si no nos gusta algo.

Abramos nuevamente los contactos, busquemos allí @Botfortest12344321 (es obligatorio iniciar la búsqueda con @), hagamos clic en “iniciar” y escribamos al bot “/Gloria a los robots”. El signo / es obligatorio, no se necesitan comillas.
El bot, por supuesto, no responderá nada.

Comprobemos que el bot ha sido creado y abrimoslo.

api.telegram.org/bot1234544311:AbcDefNNNNNNNNNNNNNNNN/getMe
donde 1234544311:AbcDefNNNNNNNNNNNNNNNN es la clave recibida anteriormente,
y obtener una línea como
{"ok": verdadero, "resultado": {""}}

Tenemos la primera frase secreta (token). Ahora necesitamos descubrir el segundo número secreto: la identificación del chat con el bot. Cada chat, grupo, etc. es individual y tiene su propio número (a veces con un signo menos, para grupos abiertos). Para saber este número, debemos solicitar en el navegador (de hecho, no es necesario en absoluto en el navegador, pero para comprenderlo mejor puede comenzar con él) la dirección (donde 1234544311:NNNNNNNNNN es su token

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

y obtener una respuesta como

{"ok":true,"resultado":[{"update_id":...,... chat":{"identificación":123456789

Necesitamos chat_id.

Comprobemos que podemos escribir en el chat manualmente: llamar a la dirección desde el navegador

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

Si recibes un mensaje de un bot en tu chat, está bien, pasas a la siguiente etapa.

De esta manera (a través del navegador) siempre podrás comprobar si hay problemas con la generación del enlace o si algo está oculto en alguna parte y no funciona.

Lo que necesitas saber antes de seguir leyendo

Telegram tiene varios tipos de chats grupales (abiertos, cerrados). Para estos chats, algunas de las funciones (por ejemplo, id) son diferentes, lo que a veces causa algunos problemas.

Supongamos que estamos a finales de 2019, e incluso el héroe de nuestro tiempo, el conocido Man-Orchestra (administrador, abogado, especialista en seguridad de la información, programador y prácticamente MVP) Evgeniy V. distingue la variable $i de una matriz, ha dominado los loops, mira, en los próximos años dominará Chocolatey, y luego Procesamiento paralelo con PowerShell и Para cada objeto paralelo vendrá.

1. Pensamos en lo que hará nuestro bot.

No tenía ninguna idea, tenía que pensar. Ya he escrito un cuaderno-bot. No quería crear un bot "que envíe algo a alguna parte". Para conectarse a Azure necesita una tarjeta de crédito, pero ¿de dónde la obtiene el estudiante? Cabe señalar que no todo es tan malo: las nubes principales ofrecen una especie de período de prueba de forma gratuita (pero aún necesita un número de tarjeta de crédito, y parece que le debitarán un dólar. No recuerdo si fue devuelto más tarde.)

Sin AI ML no es tan interesante hacer un bot-poeta-tejedor.

Decidí crear un bot que me recordará (o no) las palabras en inglés del diccionario.
Para evitar manipular la base de datos, el diccionario se almacenará en un archivo de texto y se actualizará manualmente.
En este caso, la tarea es mostrar los conceptos básicos del trabajo y no hacer al menos un producto parcialmente terminado.

2. Probar qué y cómo por primera vez

Creemos una carpeta C:poshtranslate
Primero, veamos qué tipo de PowerShell tenemos. Iniciemos ISE mediante start-run.
Powershell ise
o busque Powershell ISE en los programas instalados.
Después del lanzamiento, se abrirá el familiar "algún tipo de editor", si no hay un campo de texto, siempre puede hacer clic en "Archivo - crear nuevo".

Veamos la versión de PowerShell: escriba en el campo de texto:

get-host 

y presione F5.

Powershell ofrecerá guardar: "El script que está a punto de ejecutar se guardará", aceptamos y guardamos el archivo de PowerShell con el nombre en C: poshtranslate. myfirstbotBT100.

Después del lanzamiento, en la ventana de texto inferior obtenemos una tabla de datos:

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

Tengo 5.1 algo así, es suficiente. Si tiene un Windows 7/8 antiguo, no es gran cosa, aunque será necesario actualizar PowerShell a la versión 5, p. instrucciones.

Escriba Get-Date en la línea de comando a continuación, presione Entrar, mire la hora, vaya a la carpeta raíz con el comando
cd
y borra la pantalla con el comando cls (no, no necesitas usar rm)

Ahora veamos qué funciona y cómo: no escribamos ni siquiera el código, sino dos líneas, y tratemos de entender qué hacen. Comentemos la línea con get-host con el símbolo # y agreguemos un poco.

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

(Lo interesante es que en la lista desplegable de formato de código de Habré hay dos docenas de opciones, pero Powershell no está ahí. Dos está ahí. Perl está ahí.)

Y ejecutemos el código presionando F5 o ">" desde la GUI.

Obtenemos el siguiente resultado:

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

Ahora veamos estas dos líneas y algunos puntos interesantes para no volver a esto en el futuro.

A diferencia de Pascal (y no solo), PowerShell intenta determinar qué tipo asignar a una variable; más detalles sobre esto están escritos en el artículo Programa educativo sobre mecanografía en lenguajes de programación.
Por lo tanto, al crear una variable $TimeNow y asignarle el valor de la fecha y hora actuales (Get-Date), no tenemos que preocuparnos demasiado por qué tipo de datos habrá.

Es cierto que esta ignorancia puede doler más adelante, pero eso será para más adelante. A continuación en el texto habrá un ejemplo.
Veamos qué tenemos. Ejecutemos (en la línea de comando)

$TimeNow | Get-member

y obtener una página de texto incomprensible

Ejemplo de texto incomprensible número 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")...                                         

Como puede ver, se ha creado una variable de tipo TypeName: System.DateTime con un montón de métodos (en el sentido de lo que podemos hacer con este objeto variable) y propiedades.

Llamemos $TimeNow.DayOfYear — obtenemos el número del día del año.
Llamemos $TimeNow.DayOfYear | Get-Member - obtener TypeName: System.Int32 y un grupo de métodos.
Llamemos $TimeNow.ToUniversalTime() - y obtener la hora en UTC

Depurador

A veces sucede que es necesario ejecutar un programa hasta una determinada línea y ver el estado del programa en ese momento. Para este propósito, ISE tiene una función de depuración: alternar punto de interrupción
Coloque un punto de interrupción en algún lugar en el medio, ejecute estas dos líneas y vea cómo se ve la interrupción.

3. Comprender la interacción con el bot de Telegram

Por supuesto, se ha escrito aún más literatura sobre la interacción con el bot, con todos los getpush, etc., pero la cuestión de la teoría se puede considerar opcionalmente.

En nuestro caso es necesario:

  • Aprende a enviar algo por correspondencia.
  • Aprenda a obtener algo de la correspondencia.

3.1 Aprender a enviar algo por correspondencia y recibir de ello

Un pequeño código - parte 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

y en la Federación de Rusia, en este punto, aparece el error No se puede conectar con el servidor remoto.

O no lo recibimos; depende del operador de telecomunicaciones y de si el proxy está configurado y funcionando
Bueno, solo queda agregar un proxy. Tenga en cuenta que utilizar un proxy no cifrado y generalmente fraudulento es extremadamente peligroso para su salud.

La tarea de encontrar un proxy que funcione no es muy difícil: la mayoría de los servidores proxy http publicados funcionan. Creo que el quinto funcionó para mí.

Sintaxis usando proxy:

Invoke-WebRequest -Uri $URL4SEND -Proxy $MyProxy

Si recibes un mensaje en tu chat con un bot, entonces todo está bien, puedes seguir adelante. Si no, continúe con la depuración.

Puedes ver en qué se convierte tu cadena $URL4SEND e intentar solicitarla en el navegador, así:

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

3.2. Aprendimos a escribir “algo” en el chat, ahora intentemos leerlo

Agreguemos 4 líneas más y veamos qué hay dentro | conseguir miembro

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

Lo más interesante se nos proporciona.

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

Veamos qué hay en ellos:

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

Si todo funciona para usted, obtendrá una fila larga como:

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

Afortunadamente, en el artículo publicado anteriormente Bot de Telegram para administrador de sistemas esta línea (sí, según $MyMessageGet.RawContent | get-member es System.String), ya ha sido desmontado.

4. Procesa lo que recibes (ya sabemos cómo enviar algo)

Como ya está escrito aquí, lo más necesario está en el contenido. Echemos un vistazo más de cerca.

Primero, escribiremos un par de frases más al bot desde la interfaz web o desde el teléfono.

/message1
/message2
/message3

y busque a través del navegador la dirección que se formó en la variable $URLGET.

Veremos algo como:

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

¿Lo que es? Algún objeto complejo de matrices de objetos que contienen un identificador de mensaje de un extremo a otro, un identificador de chat, un identificador de envío y mucha otra información.

Sin embargo, no necesitamos averiguar "qué tipo de objeto es este": parte del trabajo ya está hecho por nosotros. Veamos qué hay dentro:

Lectura de mensajes recibidos o parte 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. ¿Qué debemos hacer al respecto ahora?

Guardemos el archivo resultante con el nombre myfirstbotBT105 o como más te guste, cambiemos el título y comentemos todo el código ya escrito a través de

<#start comment 105 end comment 105#>

Ahora tenemos que decidir dónde conseguir el diccionario (bueno, dónde, en el disco, en el archivo) y cómo se verá.

Por supuesto, puedes escribir un diccionario enorme directamente en el texto del guión, pero esto no viene al caso.
Entonces, veamos con qué puede funcionar PowerShell normalmente.
En general, a él no le importa con qué archivo trabajar, a nosotros no nos importa.
Tenemos una opción: txt (puedes, pero por qué), csv, xml.
¿Podemos mirar a todos? Veamos a todos.
Creemos una clase MyVocabClassExample1 y una variable $MyVocabExample1
Observo que la clase está escrita sin $

algún código #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

Intentemos escribir esto en archivos usando muestra.

Algún código #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

- y obtenemos un error en la línea Out-File -FilePath $MyFilenameExample01 -InputObject -Append $MyVocabExample2.

No quiere añadir, ah-ah, qué vergüenza.

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

Veamos qué pasa. Excelente vista de texto, pero ¿cómo exportarlo nuevamente? ¿Debería introducir algún tipo de separador de texto, como comas?

Y al final obtienes un “archivo A de valores separados por comas (CSV) DETENER ESPERAR.
#

$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 

Como puede ver fácilmente, MS no se distingue particularmente por su lógica; para un procedimiento similar, en un caso se usa -FilePath, en otro -Path.

Además, en el tercer archivo desapareció el idioma ruso, en el cuarto archivo resultó... bueno, algo pasó. #TIPO Sistema.Objeto[] 00
# “Count”,”Length”,”LongLength”,”Rank”,”SyncRoot”,”IsReadOnly”,”IsFixedSize”,”IsSynchronized”
#
Reescribámoslo un poco:

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

Parece haber ayudado, pero todavía no me gusta el formato.

Especialmente no me gusta que no pueda poner líneas de un objeto en un archivo directamente.
Por cierto, desde que empezamos a escribir en archivos, ¿podemos empezar a mantener un registro de inicio? Tenemos el tiempo como variable, podemos establecer el nombre del archivo.

Es cierto que todavía no hay nada que escribir, pero puedes pensar en la mejor manera de rotar los registros.
Probemos xml por ahora.

Algunos 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

Exportar a xml tiene muchas ventajas: legibilidad, exportación del objeto completo y no es necesario realizar una inversión.

Vamos a intentar leer el archivo xml.

Un poco de lectura de xml

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

Volvamos a la tarea. Escribimos un archivo de prueba, lo leímos, el formato de almacenamiento es claro, si es necesario, puede escribir un editor de archivos pequeño por separado para agregar y eliminar líneas.

Permítanme recordarles que la tarea consistía en hacer un pequeño robot de entrenamiento.

Formato de trabajo: Envío el comando “ejemplo” al bot, el bot me envía una palabra seleccionada al azar y una transcripción, y después de 10 segundos me envía una traducción y un comentario. Sabemos leer comandos, también nos gustaría aprender a seleccionar y verificar servidores proxy automáticamente y restablecer los contadores de mensajes al olvido.

Descomentemos todo lo comentado anteriormente como innecesario, comentemos los ejemplos ahora innecesarios con txt y csv y guardemos el archivo como versión B106.

Oh sí. Enviemos algo al bot nuevamente.

6. Despacho desde funciones y más

Antes de procesar la recepción, es necesario crear una función para enviar "al menos algo" que no sea un mensaje de prueba.

Por supuesto, en el ejemplo tendremos un solo envío y un solo procesamiento, pero ¿y si necesitamos hacer lo mismo varias veces?

Es más fácil escribir una función. Entonces, tenemos una variable de tipo objeto $MyVocabExample4AsArray, leída del archivo, en forma de una matriz de hasta dos elementos.
Vamos a leer.

Al mismo tiempo, nos ocuparemos del reloj; lo necesitaremos más adelante (de hecho, en este ejemplo no lo necesitaremos :)

Algún código #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
}

Como puede ver fácilmente, la función llama a $MyToken y $MyChatID, que estaban codificados anteriormente.

No es necesario hacer esto y si $MyToken es uno para cada bot, entonces $MyChatID cambiará según el chat.

Sin embargo, como se trata de un ejemplo, lo ignoraremos por ahora.

Dado que $MyVocabExample4AsArray no es una matriz, aunque es muy similar a una, entonces no puedes simplemente aceptarlo Solicite su longitud.

Una vez más tendremos que hacer algo que no se puede hacer - lanzarse en paracaídas no según el código - tómalo y cuenta

Algún código #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)
# Угадайте сами, какой пример легче читается посторонними людьми.

Aleatorio característica interesante. Digamos que queremos recibir 0 o 1 (solo tenemos dos elementos en la matriz). Al establecer límites 0...1, ¿obtendremos "1"?
no, no lo entenderemos, tenemos un ejemplo especial Ejemplo 2: Obtener un número entero aleatorio entre 0 y 99 Get-Random -Maximum 100
Por lo tanto, para 0..1 necesitamos establecer el tamaño 0..2, con el número máximo de elementos = 1.

7. Procesamiento de mensajes entrantes y longitud máxima de cola

¿Dónde paramos antes? tenemos la variable recibida $MyMessageGet
y $Content4Pars01 obtenido del mismo, del cual nos interesan los elementos del array Content4Pars01.result

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

Enviemos el bot /message10, /message11, /message12, /word y nuevamente /word y /hello.
Veamos qué tenemos:

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

Repasemos todo lo recibido y enviemos una respuesta si el mensaje era /palabra
el caso de constructo, lo que algunos describen como if-elseif, se llama en powershell mediante interruptor. Al mismo tiempo, el siguiente código utiliza la clave -comodín, que es completamente innecesaria e incluso dañina.

Algún código #7.1

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

Ejecutemos el script un par de veces. Obtendremos la misma palabra dos veces por cada intento de ejecución, especialmente si cometimos un error en la implementación aleatoria.

Pero detente. No enviamos /word nuevamente, entonces ¿por qué se procesa nuevamente el mensaje?

La cola para enviar mensajes al bot tiene una longitud finita (creo que 100 o 200 mensajes) y debe borrarse manualmente.

Por supuesto, esto se describe en la documentación, ¡pero tienes que leerlo!

En este caso, necesitamos el parámetro ?chat_id, y &timeout, &limit, &parse_mode=HTML y &disable_web_page_preview=true aún no son necesarios.

Documentación para La API de Telegram está aquí.
Dice en blanco e inglés:
Identificador de la primera actualización que se devolverá. Debe ser mayor en uno que el más alto entre los identificadores de actualizaciones recibidas anteriormente. De forma predeterminada, las actualizaciones comienzan con la más antigua.
sin confirmar se devuelven las actualizaciones. Una actualización se considera confirmada tan pronto como se llama a getUpdates con un compensar más alto que su update_id. El desplazamiento negativo se puede especificar para recuperar actualizaciones a partir de -offset update desde el final de la cola de actualizaciones. Todas las actualizaciones anteriores serán olvidadas.

Miremos a:

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

Sí, lo restableceremos y reescribiremos un poco la función. Tenemos dos opciones: pasar el mensaje completo a la función y procesarlo por completo en la función, o proporcionar solo el ID del mensaje y restablecerlo. Por ejemplo, el segundo parece más sencillo.

Anteriormente, nuestra cadena de consulta "todos los mensajes" se veía así

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

y se verá como

$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 

Nadie le prohíbe recibir primero todos los mensajes, procesarlos y solo después de procesar con éxito la solicitud no confirmada -> confirmada.

¿Por qué tiene sentido llamar a la confirmación después de que se haya completado todo el procesamiento? Es posible que se produzca un fallo en mitad de la ejecución y, si, en el ejemplo de un chatbot gratuito, perderse un solo mensaje no es nada especial, entonces, si estás procesando el salario de alguien o una transacción con tarjeta, el resultado puede ser peor.

Un par de líneas más de código

$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. En lugar de una conclusión

Se realizan y muestran las funciones básicas: leer mensajes, restablecer la cola, leer desde un archivo y escribir en un archivo.

Sólo quedan cuatro cosas por hacer:

  • enviar la respuesta correcta a una solicitud en el chat
  • enviar una respuesta a CUALQUIER chat al que se agregó el bot
  • ejecutando código en un bucle
  • iniciar un bot desde el programador de Windows.

Todas estas tareas son simples y se pueden realizar fácilmente leyendo la documentación sobre parámetros como
Set-ExecutionPolicy sin restricciones y -ExecutionPolicy Bypass
ciclo de la forma

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

Gracias a todos los que leyeron.

Fuente: habr.com

Añadir un comentario