Modelo para um bot de telegrama simples para alunos do 7º ao 9º ano usando Powershell

Durante conversas com um amigo, de repente descobri que as crianças da 8ª à 10ª série de sua escola não aprendem programação. Word, Excel e tudo mais. Nenhum logotipo, nem mesmo Pascal, nem mesmo VBA para Excel.

Fiquei muito surpreso, abri a Internet e comecei a ler -
Uma das atribuições de uma escola especializada é promover a educação de uma nova geração que atenda às condições da sociedade da informação no seu nível de desenvolvimento e estilo de vida.
Esta unidade curricular permitirá aos alunos consolidar na prática os conhecimentos das construções básicas da linguagem de programação Pascal. (do programa de algum ginásio para 2017)

No final, decidi passar algumas horas esboçando um exemplo de “como criar um bot simples para crianças em idade escolar”.

Abaixo está como escrever outro bot simples no Powershell e fazê-lo funcionar sem webhook, IPs brancos, servidores dedicados, máquinas virtuais implantadas na nuvem e assim por diante - em um PC doméstico normal com Windows normal.

TLDR: Outro artigo chato com erros gramaticais e factuais, nada para ler, sem humor, sem imagens.

Não há nada de novo no artigo, quase tudo o que foi escrito antes já esteve no Habré, por exemplo em artigos Instruções: Como criar bots no Telegram и Bot Telegram para administrador do sistema.
Além disso, o artigo é deliberadamente redundante para não se referir sempre à literatura educacional. Não há referências ao Gang 4, PowerShell Deep Dives ou, digamos, The 5 Pillars of the AWS Well-Architected Framework no texto.

Em vez de um prefácio, você pode pular

Sinta-se à vontade para pularEm 2006, a Microsoft lançou o PowerShell 1.0 para os então Windows XP, Vista e Server 2003. De certa forma, ele substituiu scripts cmdbat, scripts vb, Windows Script Host e JScript.

Mesmo agora, o PowerShell só pode ser considerado o próximo passo após as opções do Logo, em vez do provavelmente ainda usado Delphi (ou algo mais antigo), apesar da presença de loops, classes, funções, chamadas MS GUI, Integração Git e assim por diante.

O Powershell é usado relativamente raramente; você só pode encontrá-lo na forma de PowerShell Core, VMware vSphere PowerCLI, Azure PowerShell, MS Exchange, Desired State Configuration, Acesso Web do PowerShell e cerca de uma dúzia de programas e funções raramente usados. Talvez ele ganhe fôlego com o lançamento WSL2, mas não é exatamente.

O Powershell também tem três grandes vantagens:

  1. É relativamente simples, há muita literatura e exemplos sobre o assunto, e até em russo, por exemplo, um artigo sobre Foreach - do livro PowerShell em profundidade - sobre a diferença () e {}
  2. Ele vai com o editor ISE, incluído no Windows. Existe até algum tipo de depurador lá.
  3. É fácil ligar dele componentes para construir uma interface gráfica.

0. Preparação

Nós precisaremos:

  • PC com Windows (tenho Windows 10)
  • Pelo menos algum tipo de acesso à Internet (via NAT, por exemplo)
  • Para quem tem acesso limitado ao telegrama - instale e configure o freegate no navegador, em alguns casos difíceis, junto com Symple DNS Crypt
  • Ter um cliente de telegrama funcionando em seu telefone
  • Compreender o básico - o que é uma variável, array, loop.

Artigos abertos e lidos - Instruções: Como criar bots no Telegram и Bot Telegram para administrador do sistema

1. Vamos criar outro bot de teste.

Como todo mundo já sabe disso, e já aconteceu, você também pode pularConforme afirmado no artigo acima - Em primeiro lugar, um bot para Telegram - ainda é um aplicativo rodando do seu lado e fazendo solicitações à API do Telegram Bot. Além disso, a API é clara: o bot acessa uma URL específica com parâmetros e o Telegram responde com um objeto JSON.

Problemas relacionados: se de alguma forma desconhecida você pegar algum código de um objeto JSON e de alguma forma enviá-lo para execução (não de propósito), o código será executado para você.

O processo de criação está descrito em dois artigos acima, mas repito: em um telegrama abrimos contatos, procuramos @botfather, informamos a ele /newbot, criamos um bot Botfortest12344321, chamamos de Mynext1234bot, e recebemos uma mensagem com uma chave única do formulário 1234544311:AbcDefNNNNNNNNNNNNNN

Cuide da chave e não a entregue!

Aí você pode configurar o bot, por exemplo, proibir adicioná-lo a grupos, mas nos primeiros passos isso não é necessário.

Vamos pedir “/mybot” ao BotFather e ajustar as configurações se não gostarmos de algo.

Vamos abrir os contatos novamente, encontrar lá @Botfortest12344321 (é obrigatório iniciar a busca com @), clicar em “iniciar” e escrever para o bot “/Glória aos robôs”. O sinal / é obrigatório, as aspas não são necessárias.
O bot, claro, não responderá nada.

Vamos verificar se o bot foi criado e abri-lo.

api.telegram.org/bot1234544311:AbcDefNNNNNNNNNNNNNN/getMe
onde 1234544311:AbcDefNNNNNNNNNNNNNN é a chave recebida anteriormente,
e obter uma linha como
{"ok":true,"resultado":{""}}

Temos a primeira frase secreta (token). Agora precisamos descobrir o segundo número secreto - o ID do chat com o bot. Cada chat, grupo, etc. é individual e possui seu próprio número (às vezes com menos - para grupos abertos). Para descobrir este número, precisamos solicitar no navegador (na verdade não é necessário no navegador, mas para um melhor entendimento você pode começar por ele) o endereço (onde 1234544311:NNNNNNNNNN é o seu token

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

e obter uma resposta como

{"ok":true,"resultado":[{"update_id":...,... bate-papo":{"eu ia":123456789

Precisamos de chat_id.

Vamos verificar se podemos escrever no chat manualmente: chame o endereço do navegador

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

Se você receber uma mensagem de um bot em seu chat, tudo bem, você passa para a próxima etapa.

Desta forma (através do navegador) você sempre pode verificar se há problemas na geração do link, ou se algo está escondido em algum lugar e não funciona.

O que você precisa saber antes de continuar lendo

O Telegram possui vários tipos de chats em grupo (abertos, fechados). Para esses chats, algumas funções (por exemplo, id) são diferentes, o que às vezes causa alguns problemas.

Vamos supor que estamos no final de 2019, e até mesmo o herói do nosso tempo, o conhecido Man-Orchestra (administrador, advogado, especialista em segurança da informação, programador e praticamente MVP) Evgeniy V. distingue a variável $i de um array, dominou os loops, veja se nos próximos anos dominará o Chocolatey e então Processamento paralelo com PowerShell и Paralelo ForEach-Object virá.

1. Pensamos no que nosso bot fará

Eu não tinha ideias, tive que pensar. Eu já escrevi um caderno de bot. Eu não queria fazer um bot “que enviasse algo para algum lugar”. Para se conectar ao Azure você precisa de um cartão de crédito, mas onde o aluno o consegue? Ressalta-se que nem tudo é tão ruim: as nuvens principais dão uma espécie de período de teste de graça (mas você ainda precisa de um número de cartão de crédito - e parece que vai ser debitado um dólar dele. Não me lembro se foi devolvido mais tarde.)

Sem AI ML não é tão interessante fazer um bot-pobre-poeta-tecelão.

Decidi fazer um bot que me lembrasse (ou não) as palavras em inglês do dicionário.
Para evitar mexer no banco de dados, o dicionário será armazenado em um arquivo de texto e atualizado manualmente.
Nesse caso, a tarefa é mostrar o básico do trabalho, e não fazer pelo menos um produto parcialmente acabado.

2. Experimentando o que e como pela primeira vez

Vamos criar uma pasta C:poshtranslate
Primeiro, vamos ver que tipo de PowerShell temos, vamos iniciar o ISE via start-run
ish powershell
ou encontre o Powershell ISE nos programas instalados.
Após o lançamento, o familiar “algum tipo de editor” será aberto; se não houver campo de texto, você pode clicar em “Arquivo - criar novo”.

Vejamos a versão do PowerShell - escreva no campo de texto:

get-host 

e pressione F5.

O Powershell se oferecerá para salvar - “O script que você está prestes a executar será salvo.”, concordamos, e salve o arquivo do PowerShell com o nome em C: poshtranslate myfirstbotBT100.

Após o lançamento, na janela de texto inferior obtemos uma tabela de dados:

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

Eu tenho 5.1 alguma coisa, isso é o suficiente. Se você tem um Windows 7/8 antigo, não é grande coisa - embora o PowerShell precise ser atualizado para a versão 5 - por exemplo. instruções.

Digite Get-Date na linha de comando abaixo, pressione Enter, veja a hora, vá para a pasta raiz com o comando
cd
e limpe a tela com o comando cls (não, você não precisa usar rm)

Agora vamos verificar o que funciona e como - vamos escrever nem mesmo o código, mas duas linhas, e tentar entender o que elas fazem. Vamos comentar a linha get-host com o símbolo # e adicionar um pouco.

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

(O interessante é que na lista suspensa de formatação de código no Habré há duas dúzias de opções - mas o Powershell não está lá. O Dos está lá. O Perl está lá.)

E vamos executar o código pressionando F5 ou ">" na GUI.

Obtemos a seguinte saída:

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

Agora vamos analisar essas duas linhas e alguns pontos interessantes para não voltarmos a isso no futuro.

Ao contrário do Pascal (e não só), o próprio PowerShell tenta determinar que tipo atribuir a uma variável; mais detalhes sobre isso estão escritos no artigo Programa educacional sobre digitação em linguagens de programação
Portanto, ao criar uma variável $TimeNow e atribuir a ela o valor da data e hora atuais (Get-Date), não precisamos nos preocupar muito com que tipo de dados estarão lá.

É verdade que esta ignorância pode doer mais tarde, mas isso fica para mais tarde. Abaixo no texto haverá um exemplo.
Vamos ver o que temos. Vamos executar (na linha de comando)

$TimeNow | Get-member

e obter uma página de texto incompreensível

Exemplo de texto incompreensível 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 você pode ver, uma variável do tipo TypeName: System.DateTime foi criada com vários métodos (no sentido do que podemos fazer com este objeto variável) e propriedades.

Vamos ligar $TimeNow.DayOfYear - obtemos o número do dia do ano.
Vamos ligar $TimeNow.DayOfYear | Get-Member - pegue TypeName: System.Int32 e um grupo de métodos.
Vamos ligar $TimeNow.ToUniversalTime() - e obtenha a hora em UTC

depurador

Às vezes acontece que é necessário executar um programa até uma determinada linha e ver o estado do programa naquele momento. Para este propósito, o ISE possui uma função Debug - alternar ponto de interrupção
Coloque um ponto de interrupção em algum lugar no meio, execute essas duas linhas e veja como fica o intervalo.

3. Compreender a interação com o bot do Telegram

É claro que ainda mais literatura foi escrita sobre a interação com o bot, com todos os getpush e assim por diante, mas a questão da teoria pode ser considerada opcionalmente.

No nosso caso é necessário:

  • Aprenda a enviar algo por correspondência
  • Aprenda a obter algo por correspondência

3.1 Aprendendo a enviar algo por correspondência e receber dela

Um pouco de 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

e na Federação Russa, neste ponto, recebemos o erro Não é possível conectar-se ao servidor remoto.

Ou não recebemos - depende da operadora de telecomunicações e se o proxy está configurado e funcionando
Bem, só falta adicionar um proxy. Observe que usar um proxy não criptografado e geralmente fraudulento é extremamente perigoso para sua saúde.

A tarefa de encontrar um proxy funcional não é muito difícil - a maioria dos proxies http publicados funcionam. Acho que o quinto funcionou para mim.

Sintaxe usando proxy:

Invoke-WebRequest -Uri $URL4SEND -Proxy $MyProxy

Se você receber uma mensagem no seu chat com um bot, está tudo bem, você pode seguir em frente. Caso contrário, continue a depuração.

Você pode ver no que sua string $URL4SEND se transforma e tentar solicitá-la no navegador, assim:

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

3.2. Aprendemos a escrever “alguma coisa” no chat, agora vamos tentar ler

Vamos adicionar mais 4 linhas e ver o que tem dentro | obter membro

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

O mais interessante nos é fornecido

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

Vamos ver o que há neles:

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

Se tudo funcionar para você, você terá uma longa fila como:

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

Felizmente, no artigo publicado anteriormente Telegram bot para administrador de sistema esta linha (sim, de acordo com $MyMessageGet.RawContent | get-membro é System.String), já foi desmontado.

4. Processe o que você recebe (já sabemos como enviar algo)

Como já escrito aqui, as coisas mais necessárias estão no conteúdo. Vamos dar uma olhada mais de perto.

Primeiro, escreveremos mais algumas frases para o bot na interface da web ou no telefone

/message1
/message2
/message3

e procure no navegador o endereço que foi formado na variável $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 

O que é isso? Algum objeto complexo de matrizes de objetos contendo um identificador de mensagem ponta a ponta, identificador de bate-papo, identificador de envio e muitas outras informações.

No entanto, não precisamos descobrir “que tipo de objeto é esse” – parte do trabalho já foi feito para nós. Vamos ver o que tem dentro:

Lendo mensagens recebidas ou 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. O que devemos fazer agora?

Vamos salvar o arquivo resultante com o nome myfirstbotBT105 ou o que você preferir, alterar o título e comentar todo o código já escrito via

<#start comment 105 end comment 105#>

Agora precisamos decidir onde obter o dicionário (bem, onde - no disco, em um arquivo) e como ele ficará.

Claro, você pode escrever um dicionário enorme diretamente no texto do roteiro, mas isso não vem ao caso.
Então, vamos ver com o que o PowerShell pode funcionar normalmente.
Em geral, ele não se importa com qual arquivo trabalhar, não importa para nós.
Temos uma escolha: txt (você pode, mas por quê), csv, xml.
Podemos assistir a todos?
Vamos criar uma classe MyVocabClassExample1 e uma variável $MyVocabExample1
Noto que a classe é escrita sem $

algum 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

Vamos tentar escrever isso em arquivos usando exemplar.

Algum 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

- e obtemos um erro na linha Out-File -FilePath $MyFilenameExample01 -InputObject -Append $MyVocabExample2.

Ele não quer acrescentar, ah-ah, que pena.

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

Vamos ver o que acontece. Ótima visualização de texto - mas como exportá-lo de volta? Devo introduzir algum tipo de separador de texto, como vírgulas?

E no final você obtém um “arquivo de valores separados por vírgula (CSV) A PARE ESPERE.
#

$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 é fácil ver, o MS não se distingue particularmente pela sua lógica; para um procedimento semelhante, em um caso é usado -FilePath, em outro -Path.

Além disso, no terceiro arquivo o idioma russo desapareceu, no quarto arquivo aconteceu... bem, algo aconteceu. #TYPE Sistema.Object[] 00
# “Contagem”,”Comprimento”,”LongLength”,”Classificação”,”SyncRoot”,”IsReadOnly”,”IsFixedSize”,”IsSynchronized”
#
Vamos reescrever um pouco:

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

Parece ter ajudado, mas ainda não gosto do formato.

Eu especialmente não gosto de não poder colocar linhas de um objeto diretamente em um arquivo.
A propósito, já que começamos a gravar arquivos, podemos começar a manter um log de inicialização? Temos o tempo como variável, podemos definir o nome do arquivo.

É verdade que ainda não há nada para escrever, mas você pode pensar na melhor forma de girar os logs.
Vamos tentar o xml por enquanto.

Algum 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 para xml tem muitas vantagens - legibilidade, exportação de todo o objeto e não há necessidade de realizar uppend.

Vamos tentar leia o arquivo xml.

Uma pequena leitura do xml

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

Voltemos à tarefa. Escrevemos um arquivo de teste, lemos, o formato de armazenamento é claro, se necessário, você pode escrever um pequeno editor de arquivos separado para adicionar e excluir linhas.

Deixe-me lembrá-lo de que a tarefa era fazer um pequeno bot de treinamento.

Formato de trabalho: envio o comando “exemplo” para o bot, o bot me envia uma palavra e uma transcrição selecionadas aleatoriamente e após 10 segundos me envia uma tradução e um comentário. Sabemos como ler comandos, também gostaríamos de aprender como selecionar e verificar proxies automaticamente e redefinir os contadores de mensagens para o esquecimento.

Vamos descomentar tudo o que foi comentado anteriormente como desnecessário, comentar os exemplos agora desnecessários com txt e csv e salvar o arquivo como versão B106

Oh sim. Vamos enviar algo para o bot novamente.

6. Envio de funções e muito mais

Antes de processar a recepção, é necessário criar uma função para enviar “pelo menos alguma coisa” que não seja uma mensagem de teste.

Claro que no exemplo teremos apenas um envio e apenas um processamento, mas e se precisarmos fazer várias vezes a mesma coisa?

É mais fácil escrever uma função. Assim, temos uma variável do tipo object $MyVocabExample4AsArray, lida do arquivo, na forma de um array de até dois elementos.
Vamos ler.

Ao mesmo tempo, trataremos do relógio; precisaremos dele mais tarde (na verdade, neste exemplo não precisaremos dele :)

Algum 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 você pode ver facilmente, a função chama $MyToken e $MyChatID, que foram codificados anteriormente.

Não há necessidade de fazer isso, e se $MyToken for um para cada bot, então $MyChatID mudará dependendo do chat.

No entanto, como este é um exemplo, iremos ignorá-lo por enquanto.

Como $MyVocabExample4AsArray não é um array, embora seja muito semelhante a um, então você não pode simplesmente aceitar solicite seu comprimento.

Mais uma vez teremos que fazer algo que não pode ser feito - pára-quedas não está de acordo com o código - pegue e conte

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

Aleatória recurso interessante. Digamos que queremos receber 0 ou 1 (temos apenas dois elementos no array). Ao definir limites 0..1, obteremos “1”?
não - não vamos entender, temos um exemplo especial Exemplo 2: Obtenha um número inteiro aleatório entre 0 e 99 Get-Random -Maximum 100
Portanto, para 0..1 precisamos definir o tamanho 0..2, com o número máximo do elemento = 1.

7. Processamento de mensagens recebidas e comprimento máximo da fila

Onde paramos antes? temos a variável recebida $MyMessageGet
e $Content4Pars01 obtido dele, dos quais estamos interessados ​​nos elementos do array Content4Pars01.result

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

Vamos enviar o bot /message10, /message11, /message12, /word e novamente /word e /hello.
Vamos ver o que temos:

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

Vamos analisar tudo o que foi recebido e enviar uma resposta se a mensagem foi /word
o caso da construção, o que alguns descrevem como if-elseif, é chamado no PowerShell através do interruptor. Ao mesmo tempo, o código abaixo usa a chave -wildcard, que é completamente desnecessária e até prejudicial.

Algum código #7.1

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

Vamos executar o script algumas vezes. Obteremos a mesma palavra duas vezes para cada tentativa de execução, especialmente se cometermos um erro na implementação do aleatório.

Mas pare. Não enviamos /word novamente, então por que a mensagem está sendo processada novamente?

A fila de envio de mensagens para o bot tem comprimento finito (100 ou 200 mensagens, eu acho) e deve ser limpa manualmente.

É claro que isso está descrito na documentação, mas você precisa lê-la!

Neste caso, precisamos do parâmetro ?chat_id, e &timeout, &limit, &parse_mode=HTML e &disable_web_page_preview=true ainda não são necessários.

Documentação para API do telegrama está aqui
Diz em branco e inglês:
Identificador da primeira atualização a ser retornada. Deve ser maior em um que o maior entre os identificadores de atualizações recebidas anteriormente. Por padrão, as atualizações começam com a mais antiga
não confirmado atualização são retornados. Uma atualização é considerada confirmada assim que getUpdates é chamado com um compensar superior do que seu update_id. O deslocamento negativo pode ser especificado para recuperar atualizações começando em -offset update do final da fila de atualizações. Todas as atualizações anteriores serão esquecidas.

Vamos olhar para:

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

Sim, e vamos redefini-lo e reescrever um pouco a função. Temos duas opções: passar a mensagem inteira para a função e processá-la inteiramente na função ou fornecer apenas o ID da mensagem e redefini-la. Por exemplo, o segundo parece mais simples.

Anteriormente, nossa string de consulta “todas as mensagens” parecia

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

e vai parecer

$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 

Ninguém proíbe você primeiro de receber todas as mensagens, processá-las e somente após o processamento bem-sucedido da solicitação não confirmada -> confirmada.

Por que faz sentido ligar para confirmação após a conclusão de todo o processamento? Uma falha é possível no meio da execução e se, no exemplo de um chatbot gratuito, perder uma única mensagem não for nada especial, então se você estiver processando o salário de alguém ou uma transação com cartão, o resultado pode ser pior.

Mais algumas linhas 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. Em vez de uma conclusão

Funções básicas - leitura de mensagens, redefinição de fila, leitura de arquivo e gravação em arquivo são feitas e mostradas.

Restam apenas quatro coisas a fazer:

  • enviando a resposta correta a uma solicitação no chat
  • enviando uma resposta para QUALQUER chat ao qual o bot foi adicionado
  • executando código em um loop
  • iniciando um bot a partir do agendador do Windows.

Todas essas tarefas são simples e podem ser facilmente realizadas lendo a documentação sobre parâmetros como
Set-ExecutionPolicy irrestrito e -ExecutionPolicy Bypass
ciclo do formulário

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

Obrigado a todos que leram.

Fonte: habr.com

Adicionar um comentário