Durante una conversación con un amigo, me sorprendió descubrir que en su escuela no enseñan programación a los niños de 8º a 10º grado. Solo Word, Excel y eso es todo. Ni logo, ni siquiera Pascal, ni VBA para Excel.
Me sorprendí mucho, abrí internet y comencé a leer —
Una de las tareas de la escuela especializada es fomentar la educación de una nueva generación que corresponda a las condiciones de la sociedad de la información según su nivel de desarrollo y estilo de vida.
Este curso permitirá consolidar en la práctica los conocimientos de los estudiantes sobre las estructuras básicas del lenguaje de programación Pascal. (de un programa de algún gimnasio de 2017)
Al final, decidí gastar un par de horas y esbozar un ejemplo de «cómo crear un bot simple — para estudiantes».
A continuación, sobre cómo escribir otro bot simple en Powershell y hacerlo funcionar sin webhook, IP blancas, servidores dedicados, máquinas virtuales desplegadas en la nube y demás — en una PC doméstica común con Windows normal.
TLDR: Otro artículo aburrido con errores gramaticales y fácticos, no hay nada que leer, falta de humor, falta de imágenes.
No hay nada nuevo en el artículo, casi todo lo escrito ya estaba en Habr, por ejemplo, en artículos como y .
Además, el artículo es deliberadamente redundante, para no tener que referirse a la literatura de estudio cada vez. No hay referencias a la banda 4, PowerShell Deep Dives o, digamos, The 5 Pillars of the AWS Well-Architected Framework en el texto.
En lugar de un prefacio, se puede omitir
Confiadamente lo omitimosEn 2006, Microsoft lanzó PowerShell 1.0 para Windows XP, Vista y 2003 Server. De alguna manera, reemplazó cosas como los scripts de cmdbat, scripts vb, Windows Script Host y JScript.
Incluso ahora, PowerShell solo puede considerarse como el siguiente paso después de las opciones de Logo, en lugar de ser probablemente todavía utilizado Delphi (o algo más antiguo), a pesar de tener bucles, clases, funciones, invocación de MS GUI, y así sucesivamente.
PowerShell se utiliza relativamente poco, se puede encontrar en forma de PowerShell Core, VMware vSphere PowerCLI, Azure PowerShell, MS Exchange, Desired State Configuration, y una docena más de programas y funciones poco utilizados. Quizás resurgirá con el lanzamiento de , pero eso no es seguro.
PowerShell tiene tres grandes ventajas:
- Es relativamente sencillo, hay mucha literatura y ejemplos sobre él, incluso en ruso, por ejemplo, un artículo sobre Foreach — del libro — sobre la diferencia entre () y {}
- Viene junto con el editor , incluido en Windows. Allí incluso hay algún depurador.
- Se pueden invocar fácilmente desde él .
0. Preparación.
Necesitaremos:
- Un PC con Windows (tengo Windows 10)
- Alguna conexión a Internet (a través de NAT, por ejemplo)
- Para aquellos que tienen acceso limitado a Telegram: un Freegate instalado y configurado en el navegador, en algunos casos complejos junto con Symple DNS Crypt
- Tener un cliente de Telegram funcional en el teléfono
- Entender lo básico: qué es una variable, un array, un ciclo.
Artículos abiertos y leídos — y
1. Crearemos un nuevo bot de prueba.
Dado que todos ya lo saben y ha sido mencionado antes, también se puede omitir.Como se dice en el artículo anterior — Primero que todo, un bot para Telegram — es, ante todo, una aplicación que se ejecuta en su lado y realiza solicitudes a la Telegram Bot API. Y la API es clara: el bot se dirige a una URL específica con parámetros, y Telegram responde con un objeto JSON.
Los problemas relacionados con esto: si de alguna manera desconocida toma un código de un objeto JSON y lo envía a ejecutar (sin intención) — el código se ejecutará.
El proceso de creación está descrito en dos artículos anteriores, pero repito: en Telegram abrimos contactos, buscamos @botfather, le decimos /newbot, creamos el bot Botfortest12344321, lo llamamos Mynext1234bot, y recibimos un mensaje con una clave única del tipo 1234544311:AbcDefNNNNNNNNNNNNN
¡Protege esa clave y no la compartas!
Luego se puede configurar el bot, por ejemplo, prohibir que se agregue a grupos, pero en los primeros pasos no es necesario.
Le preguntaremos a BotFather «/mybot» y ajustaremos la configuración si algo no nos gusta.
Nuevamente abriremos los contactos, buscaremos @Botfortest12344321 (comenzar la búsqueda con @ es obligatorio), presionaremos «iniciar» y escribiremos al bot «/Gloria a los robots». El símbolo / es obligatorio, las comillas no son necesarias.
El bot, por supuesto, no responderá.
Verificaremos que el bot se ha creado — lo abriremos.
:AbcDefNNNNNNNNNNNNN/getMe
donde 1234544311:AbcDefNNNNNNNNNNNNN es la clave obtenida anteriormente,
y obtendremos una cadena del tipo
{"ok":true,"result":{""}}
Ya tenemos la primera frase secreta (token). Ahora necesitamos conocer el segundo número secreto: el ID del chat con el bot. Cada chat, grupo, etc., es único y tiene su propio número (a veces con un signo negativo, para grupos abiertos). Para averiguar este número, necesitamos solicitar en el navegador (realmente no es necesario hacerlo en el navegador, pero para una mejor comprensión, se puede comenzar con eso) la dirección (donde 1234544311:NNNNNNNNN es su token
https://api.telegram.org/bot1234544311:NNNNNNNNN/getUpdates
y obtener una respuesta del tipo
{«ok»:true,«result»:[{«update_id»:…,… chat«:{«id»:123456789
Necesitamos precisamente chat_id.
Verificaremos que podemos escribir en el chat manualmente: llamaremos desde el navegador a la dirección
https://api.telegram.org/botvartu_token/sendMessage?chat_id=123456789&text="La vida es un movimiento dirigido"Si le ha llegado un mensaje al chat del bot, está bien, pasas a la siguiente etapa.
De esta manera (a través del navegador), siempre puedes verificar dónde están los problemas: si tú al generar el enlace, o si hay algo que está oculto y no funciona.
Lo que necesitas saber antes de continuar leyendo
En Telegram hay varios tipos de chats grupales (abiertos, cerrados). Para estos chats parte de las funciones (por ejemplo, id) difieren, lo que a veces causa ciertos problemas.
Asumamos que estamos a finales de 2019, y hasta el héroe de nuestro tiempo, el conocido Hombre-Orquesta (administrador, abogado, especialista en seguridad de la información, programador y prácticamente MVP) Evgeny V. distingue la variable $i de un array, ha dominado los ciclos, y esperemos que en los próximos dos años aprenda Chocolatey, y después y llegue.
1. Pensemos, ¿qué hará nuestro bot?
No tenía ideas, tuve que pensar. Ya había creado un bot-notepad. No quería hacer un bot que "envíe algo a algún lado". Para conectar Azure se necesita una tarjeta de crédito, ¿pero de dónde la saca un estudiante? Es importante señalar que no todo está tan mal: las principales nubes ofrecen algún período de prueba gratuito (pero aún se necesita un número de tarjeta de crédito — y parece que se cobrará un dólar. No recuerdo si se devolvió después.)
Sin AI ML, hacer un bot común no es tan interesante.
Decidí hacer un bot que me recuerde (o no) palabras en inglés del diccionario.
El diccionario, para no lidiar con una base de datos, estará en un archivo de texto y se actualizará manualmente.
En este caso, la tarea es mostrar los fundamentos del trabajo, y no crear un producto que esté al menos parcialmente terminado.
2. Probamos qué y cómo por primera vez
Crearemos la carpeta C:poshtranslate
Para empezar, veamos qué tenemos en PowerShell, iniciemos ISE a través de Ejecutar
powershell ise
o buscaremos PowerShell ISE en los programas instalados.
Al iniciar, se abrirá un editor 'normal y familiar'; si no hay campo de texto, siempre se puede hacer clic en 'Archivo - crear nuevo'.
Veamos la versión de PowerShell; escribiremos en el campo de texto:
get-host
y presionamos F5.
PowerShell nos sugerirá guardar: 'El script que estás a punto de ejecutar se guardará.', aceptamos y guardamos en C:poshtranslate el archivo de PowerShell con el nombre myfirstbotBT100.
Al ejecutar, en la ventana de texto inferior obtendremos una tabla de datos:
Nombre : Windows PowerShell ISE Host
Versión : 5.1.(y así sucesivamente)
Tengo 5.1 y algo más, eso es suficiente. Si tienes Windows 7/8 antiguo, no hay problema; sin embargo, PowerShell debe actualizarse a la versión 5, por ejemplo, a través de .
Escribamos en la línea de comandos de abajo Get-Date, presionamos Enter, observamos la hora y accedemos a la carpeta raíz con el comando
cd
y limpiamos la pantalla con el comando cls (no, no se debe usar rm)
Ahora comprobemos qué y cómo funciona; escribamos no solo código, sino dos líneas, y tratemos de entender qué hacen. Comentaremos la línea con get-host con el símbolo # y añadiremos algo.
# Пример шаблона бота
# get-host
<# это пример многострочного комментария #>
$TimeNow = Get-Date
$TimeNow
(Lo interesante. En la lista desplegable de estilo del código en Habr, hay una veintena de opciones, pero no hay PowerShell. Hay DOS. Hay Perl.)
Y ejecutamos el código presionando F5 o '>' desde la GUI.
Obtendremos la salida:
Sábado, 8 de diciembre de 2019 21:00:50 PM (o algo así)
Ahora analicemos estas dos líneas y algunos momentos interesantes para no volver a esto en el futuro.
A diferencia de Pascal (y no solo), PowerShell intenta determinar por sí mismo qué tipo asignar a la variable; más sobre esto está escrito en el artículo
Por lo tanto, al crear la variable $TimeNow y asignarle el valor de la fecha y hora actuales (Get-Date), no debemos preocuparnos demasiado por qué tipo de datos tendrá.
Sin embargo, no saber esto puede causar problemas más adelante, pero eso es después. A continuación en el texto habrá un ejemplo.
Veamos qué obtuvimos. Ejecutaremos (en la línea de comandos)
$TimeNow | Get-membery obtendremos una página de texto confuso
Ejemplo de texto confuso número 1
PS C:> $TimeNow | Get-member
TypeName: System.DateTime
Nombre TipoMiembro Definición
---- ---------- ----------
Agregar <b>Método </b>datetime Agregar(timespan valor)
..
PistaVisual NotaPropiedad TipoPistaVisual PistaVisual=DateTime
Fecha <b>Propiedad </b>datetime Fecha {get;}
Año Propiedad int Año {get;}
..
FechaHora PropiedadDeScript System.Object FechaHora {get=if ((& { Set-StrictMode -Version 1; $this.PistaVisual }) -ieq "Fecha")...
Como se puede ver, se creó una variable de tipo TypeName: System.DateTime con un montón de métodos (en el sentido de que podemos hacer con este objeto variable) y propiedades.
Llamaremos $TimeNow.DayOfYear — obtendremos el número del día del año.
Llamaremos $TimeNow.DayOfYear | Get-Member — obtendremos Tipo: System.Int32 y grupo de métodos.
Llamaremos $TimeNow.ToUniversalTime() — y obtendremos la hora en UTC
Depurador
A veces es necesario ejecutar un programa hasta una cierta línea y ver el estado del programa en ese momento. Para esto, en ISE hay una función de Depuración — activar punto de interrupción.
Establece un punto de interrupción en algún lugar a la mitad, ejecuta estas dos líneas y observa cómo se ve la detención.
3. Entendiendo la interacción con el bot de Telegram
Por supuesto, sobre la interacción con el bot, con todas las getpush y demás, se ha escrito aún más literatura, sin embargo, la cuestión de la teoría se puede considerar como opcional.
En nuestro caso es necesario:
- Aprender a enviar algo en la conversación
- Aprender a recibir algo de la conversación
3.1 Aprendiendo a enviar algo en la conversación y recibirlo
Un poco de código — parte 3
Write-output "Esta es la parte 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 vida es un movimiento dirigido - " + $TimeNow
$URL4SEND = "https://api.telegram.org/bot$MyToken/sendMessage?chat_id=$MyChatID&text=$MyText01"
Invoke-WebRequest -Uri $URL4SEND
y en Rusia en este lugar recibimos el error Unable to connect to the remote server.
O no lo recibimos — depende del operador de telecomunicaciones y de si está configurado y funcionando el proxy.
Bueno, solo queda agregar el proxy. Tenga en cuenta que el uso de un proxy no cifrado y en general un proxy no confiable es extremadamente peligroso para su salud.
La tarea de encontrar un proxy funcional no es muy complicada — la mayoría de los proxies http publicados funcionan. Me parece que me funcionó el quinto en la cuenta.
Sintaxis utilizando un proxy:
Invoke-WebRequest -Uri $URL4SEND -Proxy $MyProxy
Si recibiste un mensaje en tu chat con el bot — entonces todo está bien, puedes continuar. Si no — sigue depurando.
Puedes ver en qué se convierte tu cadena $URL4SEND y intentar solicitarla en el navegador, por ejemplo así:
$URL4SEND2 = '"'+$URL4SEND+'"'
start chrome $URL4SEND2
3.2. Hemos aprendido a escribir «algo» en el chat, ahora intentemos leer
Añadiremos 4 líneas más y veremos qué hay dentro a través de | 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
Lo más interesante nos lo proporciona
Content Propiedad string Content {get;}
ParsedHtml Propiedad mshtml.IHTMLDocument2 ParsedHtml {get;}
RawContent Propiedad string RawContent {get;set;}Veamos qué hay en ellos:
Write-Host "ParsedHtml"
$MyMessageGet.ParsedHtml # aquí hay algo interesante
Write-Host "RawContent"
$MyMessageGet.RawContent # y aquí también hay algo interesante, pero además es legible.
Write-Host "Content"
$MyMessageGet.Content
Si todo funciona, obtendrás una cadena larga similar a:
{"ok":true,"result":[{"update_id":12345678,
"message":{"message_id":3,"from":{"id"Afortunadamente, en un artículo anterior sobre un bot de Telegram para administradores de sistemas, esta línea (sí, de acuerdo a $MyMessageGet.RawContent | get-member — es un System.String), ya fue analizada.
4. Procesar lo recibido (ya sabemos cómo enviar algo)
Como ya se ha mencionado , lo más relevante se encuentra en content. Vamos a examinarlo más de cerca.
Primero escribamos un par de frases más al bot desde la interfaz web o desde el teléfono
/message1
/message2
/message3y veamos 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 ¿Qué es esto? Un objeto complejo hecho de arreglos de objetos, que contiene un identificador de mensaje, un identificador de chat, un identificador de envío y mucha más información.
Sin embargo, no necesitamos analizar «qué es este objeto» — parte del trabajo ya se ha hecho por nosotros. Veamos qué hay dentro:
Leyendo los 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é hacemos ahora con esto?
Guardemos el archivo recibido con el nombre myfirstbotBT105 o el que prefieras, cambiemos el encabezado y comentemos todo el código escrito hasta ahora a través de
<#start comment 105 end comment 105#>
Ahora necesitamos decidir de dónde obtendremos el diccionario (bueno, ¿dónde? — en el disco en un archivo) y cómo será.
Claro, se podría llenar un diccionario enorme directamente en el texto del script, pero eso no es lo ideal.
Así que veamos con qué puede trabajar normalmente PowerShell.
En realidad, a PowerShell no le importa con qué archivo trabajar, pero a nosotros sí.
Tenemos las siguientes opciones: txt (se puede, pero ¿para qué?), csv, xml.
O podemos ver todos. Veamos todos.
Creamos la clase MyVocabClassExample1 y la variable $MyVocabExample1
observando que la clase se escribe sin $
un poco de código #5
write-host "Esta es la parte 5"
class MyVocabClassExample1 {
[string]$Original # palabra
[string]$Transcript
[string]$Translate
[string]$Example
[int]$VocWordID # un punto muy interesante. El uso de int con sus limitaciones puede a veces llevar a consecuencias inesperadas, como el reciente caso con SSD HPE. Inicialmente no quise añadir este elemento, pero luego decidí hacerlo y comentarlo.
}
$MyVocabExample1 = [MyVocabClassExample1]::new()
$MyVocabExample1.Original = "Apple"
$MyVocabExample1.Transcript = "[ ˈapəl ]"
$MyVocabExample1.Translate = "Manzana"
$MyVocabExample1.Example = "Una manzana es una fruta dulce y comestible producida por un manzano (Malus domestica)"
# $MyVocabExample1.$VocWordID = 1
$MyVocabExample2 = [MyVocabClassExample1]::new()
$MyVocabExample2.Original = "Pear"
$MyVocabExample2.Transcript = "[ pe(ə)r ]"
$MyVocabExample2.Translate = "Pera"
$MyVocabExample2.Example = "El árbol y arbusto de pera son especies del género Pyrus"
# $MyVocabExample1.$VocWordID = 2
Intentemos escribir esto en archivos según .
Un poco de código #5.1
Write-Host $ScriptDir # espero que no hayas comentado $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 obtendremos un error en la línea Out-File -FilePath $MyFilenameExample01 -InputObject -Append $MyVocabExample2.
No quiere añadir, oh no, qué lástima.
$MyVocabExample3AsArray = @($MyVocabExample1,$MyVocabExample2)
Out-File -FilePath $MyFilenameExample02 -InputObject $MyVocabExample3AsArray
notepad $MyFilenameExample02
Veamos qué ha salido. Una hermosa vista de texto — ¿pero cómo exportarlo de nuevo? ¿Deberíamos ingresar algunos delimitadores de texto, como comas?
Y al final obtener "un archivo con delimitadores - comas, valores separados por comas (CSV) A .
#
$MyFilenameExample03 = $ScriptDir + "Example03.csv"
$MyFilenameExample04 = $ScriptDir + "Example04.csv"
Export-Csv -Path $MyFilenameExample03 -InputObject $MyVocabExample1
Export-Csv -Path $MyFilenameExample03 -InputObject $MyVocabExample2 -Append
Export-Csv -Path $MyFilenameExample04 -InputObject $MyVocabExample3AsArray
Es fácil ver que Microsoft no se destacó en lógica, en un caso se usa -FilePath, en otro -Path para un procedimiento similar.
Además, en el tercer archivo se perdió el idioma ruso, en el cuarto archivo salió... bueno, algo salió. #TYPE System.Object[] 00
# „Count“,»Length»,«LongLength»,«Rank»,«SyncRoot»,«IsReadOnly»,«IsFixedSize»,«IsSynchronized»
#
Reescribamos un poco:
Export-Csv -Path $MyFilenameExample03 -InputObject $MyVocabExample1 -Encoding Unicode
Export-Csv -Path $MyFilenameExample03 -InputObject $MyVocabExample2 -Append -Encoding Unicode
notepad $MyFilenameExample03
notepad $MyFilenameExample04
Parece que ayudó — pero el formato aún no me gusta.
Particularmente no me gusta que no puedo poner directamente las cadenas del objeto en un archivo.
Por cierto, ya que empezamos a escribir en archivos, ¿podríamos comenzar a llevar un registro de inicio? Ya tenemos el tiempo como variable y sabemos nombrar el archivo.
Escribir, de hecho, por ahora no hay nada que decir, pero se puede pensar en cómo hacer mejor la rotación de logs.
Por ahora intentemos con xml.
Un poco 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
La exportación a xml tiene muchas ventajas: legibilidad, exportación de todo el objeto, y no es necesario realizar un uppend.
Intentemos .
Un poco de lectura desde xml
$MyFilenameExample06 = $ScriptDir + "Example06.xml"
$MyVocabExample4AsArray = Import-Clixml -Path $MyFilenameExample06
# $MyVocabExample4AsArray
# $MyVocabExample4AsArray[0]
# Y un poco sobre los matices que no son evidentes. Powershell a veces se comporta de manera inesperada.
# Por ejemplo, estas dos salidas son diferentes
# Write-Output $MyVocabExample4AsArray
# write-host $MyVocabExample4AsArray
Volvamos a la tarea. Hemos escrito un archivo de prueba, lo hemos leído, el formato de almacenamiento es comprensible, si es necesario, se puede escribir un pequeño editor de archivos para agregar y eliminar líneas.
Recuerdo que la tarea era crear un pequeño bot de capacitación.
Formato de trabajo: yo envío al bot el comando 'ejemplo', el bot me envía una palabra elegida al azar y su transcripción, y después de 10 segundos envía la traducción y un comentario. Sabemos leer comandos, aunque también deberíamos aprender a seleccionar y verificar proxies automáticamente, y restablecer contadores de mensajes a cero.
Descomentaremos todo lo que estaba comentado previamente como innecesario, comentaremos los ejemplos de txt y csv que se volvieron innecesarios, y guardaremos el archivo como versión B106.
Ah, sí. Enviaremos algo al bot otra vez.
6. Envío desde funciones y más
Antes de procesar la recepción, debemos hacer una función para enviar 'algo', además del mensaje de prueba.
Por supuesto, en nuestro ejemplo solo habrá un envío y solo desde un procesamiento, pero, ¿qué pasaría si necesitamos hacer lo mismo varias veces?
Es más fácil escribir una función. Así que tenemos una variable de tipo objeto $MyVocabExample4AsArray, leída desde el archivo, en forma de un arreglo con exactamente dos elementos.
Al mismo tiempo, veremos cómo funcionan los relojes, ya que luego lo necesitaremos (en realidad, en este ejemplo, no será necesario 🙂
Un poco de código #6.1
Escribe-Salida "Esta es la Parte 6"
$Timezone = (Obtener-ZonaHoraria)
SI($Timezone.SoportaHorarioDeVerano -eq $True){
$TimeAdjust = ($Timezone.BaseUtcOffset.TotalSeconds + 3600) } # hora ajustada
OTRA{$TimeAdjust = ($Timezone.BaseUtcOffset.TotalSeconds)
}
función MiPrimeraFunción($UnEjemploParaFunción1){
$TimeNow = Obtener-Feccha
$TimeNow.ToUniversalTime()
# $MyText02 = $TimeNow + " " + $UnEjemploParaFunción1 # y aquí obtendremos un error
$MyText02 = $UnEjemploParaFunción1 + " " + $TimeNow # aquí no obtendremos error, quien adivine por qué - ¡bien hecho!
$URL4SendFromFunction = "https://api.telegram.org/bot$MyToken/sendMessage?chat_id=$MyChatID&text=$MyText02"
Invocar-SolicitudWeb -Uri $URL4SendFromFunction -Proxy $MyProxy
}
Como puedes ver fácilmente, en la función se llaman $MyToken y $MyChatID, que fueron asignados previamente.
Esto no se debe hacer y, si $MyToken es uno para cada bot, $MyChatID cambiará dependiendo del chat.
Sin embargo, dado que este es un ejemplo, por ahora lo ignoraremos.
Dado que $MyVocabExample4AsArray no es un array, aunque se asemeja mucho a uno, no se puede simplemente consultar su longitud.
Tendremos que hacer una vez más lo que no se debe hacer: descender fuera del código: contar
Un poco de código #6.2
$MaxRandomExample = 0
foreach ($Obj in $MyVocabExample4AsArray) {
$MaxRandomExample ++
}
Escribe-Salida $MaxRandomExample
$RandomExample = Obtener-Aleatorio -Mínimo 0 -Máximo ($MaxRandomExample)
$TextForExample1 = $MyVocabExample4AsArray[$RandomExample].Original
# MiPrimeraFunción($TextForExample1)
# o en una sola línea
# MiPrimeraFunción($MyVocabExample4AsArray[Obtener-Aleatorio -Mínimo 0 -Máximo ($MaxRandomExample -1)].Ejemplo)
# Adivina tú mismo, qué ejemplo es más fácil de leer por personas externas.
Aleatorio . Supongamos que queremos obtener 0 o 1 (solo tenemos dos elementos en el array). Al establecer los límites en 0..1, ¿obtendremos "1"?
no — no lo obtendremos, hemos hecho un ejemplo específico Ejemplo 2: Obtener un número entero aleatorio entre 0 y 99 Obtener-Aleatorio -Máximo 100
Por lo tanto, para 0..1, tendremos que establecer el tamaño en 0..2, siendo el número máximo de elemento = 1.
7. Manejo de mensajes recibidos y longitud máxima de la cola
¿En qué nos quedamos antes? tenemos la variable obtenida $MyMessageGet
y $Content4Pars01 obtenido de ella, de los cuales nos interesan los elementos del array Content4Pars01.result
$Content4Pars01.result[0].update_id
$Content4Pars01.result[0].message
$Content4Pars01.result[0].message.text Enviaremos al bot /message10, /message11, /message12, /word y una vez más /word y /hola.
Veamos qué hemos recibido:
$Content4Pars01.result[0].message.text
$Content4Pars01.result[2].message.text Recorremos todo lo recibidos y enviamos una respuesta si el mensaje era /word
la construcción case of, lo que algunos describen como if-elseif, en powershell se llama . En el código a continuación se ha utilizado la clave -wildcard, lo cual no es necesario e incluso puede ser perjudicial.
Un poco de código #7.1
Write-Output "Esto es parte 7"
Foreach ($Result in $Content4Pars01.result) # Sí, se puede hacer más rápido
{
switch -wildcard ($Result.message.text)
{
"\/word" {MyFirstFunction($TextForExample1)}
}
}
Ejecutemos el script un par de veces. Obtendremos la misma palabra dos veces en cada intento de ejecución, especialmente si nos equivocamos en la implementación de random.
Pero espera. No enviamos \/word de nuevo, ¿por qué se procesa el mensaje de nuevo?
La cola para enviar mensajes al bot tiene una longitud finita (creo que 100 o 200 mensajes), y debe limpiarse manualmente.
En la documentación, por supuesto, está descrito, ¡pero hay que leerla!
En este caso, necesitamos el parámetro ?chat_id, y &timeout, &limit, &parse_mode=HTML y &disable_web_page_preview=true no son necesarios por ahora.
Documentación sobre Está claramente escrito en inglés:
Identifier of the first update to be returned. Must be greater by one than the highest among the identifiers of previously received updates. By default, updates starting with the earliest
unconfirmed update are returned. An update is considered confirmed as soon as getUpdates is called with an offset higher than its update_id. Se puede especificar un desplazamiento negativo para recuperar actualizaciones comenzando desde -offset update desde el final de la cola de actualizaciones. Todas las actualizaciones anteriores se olvidarán.
Veamos:
$Content4Pars01.result[0].update_id
$Content4Pars01.result[1].update_id
$Content4Pars01.result | select -last 1
($Content4Pars01.result | select -last 1).update_idY lo reiniciaremos — reharemos un poco la función. Tenemos dos opciones: pasar todo el mensaje a la función y procesarlo completamente dentro de ella, o solo enviar el ID del mensaje y también reiniciarlo. Por ejemplo, la segunda opción parece más sencilla.
Antes nuestra cadena de consulta "de todos los mensajes" parecía así
$URLGET = "https:\/\/api.telegram.org\/bot$MyToken\/getUpdates"y se verá así
$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 prohíbe primero obtener todos los mensajes, procesarlos y solo después de un procesamiento exitoso solicitar unconfirmed -> confirmed.
¿Por qué tiene sentido llamar a la confirmación después de completar todos los procesos? Puede haber un fallo a mitad de la ejecución, y si, por ejemplo, para un chatbot gratuito perder un mensaje individual no es gran cosa, pero 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 #se supone que debes corregir el error aquí por tu cuenta.
$URLGET1 = "https://api.telegram.org/bot$mytoken/getUpdates?offset=$LastMessageId&limit=100"
Invoke-WebRequest -Uri $URLGET1 -Method Get -Proxy $MyProxy
8. En lugar de conclusión
Las funciones principales — lectura de mensajes, reinicio de cola, lectura de archivo y escritura en archivo están realizadas y mostradas.
Solo quedan por hacer cuatro cosas:
- enviar la respuesta correcta a la solicitud en el chat
- enviar la respuesta a CUALQUIER chat en el que se agregó el bot
- ejecutar el código en un bucle
- iniciar el bot desde el programador de Windows.
Todas estas tareas son simples y se pueden implementar fácilmente leyendo la documentación sobre parámetros como
Set-ExecutionPolicy Unrestricted y -ExecutionPolicy Bypass
bucle del tipo
$TimeToSleep = 3 # sondeo cada 3 segundos
$TimeToWork = 10 # minutos
$HowManyTimes = $TimeToWork*60/$TimeToSleep # contador para el bucle
$MainCounter = 0
for ($MainCounter=0; $MainCounter -le $HowManyTimes) {
sleep $TimeToSleep
$MainCounter ++
Gracias a todos los que leyeron hasta aquí.
Fuente: habr.com
