La ŝablono de la plej simpla telegrambot por lernejanoj en klasoj 7-9 sur Powershell

Dum konversacioj kun amiko, mi subite eksciis, ke infanoj en la klasoj 8-10 en sia lernejo tute ne estas instruitaj pri programado. Word, Excel kaj ĉio. Neniu emblemo, eĉ ne Paskalo, eĉ ne VBA por Excel.

Mi estis tre surprizita, malfermis la Interreton kaj komencis legi -
Unu el la taskoj de faka lernejo estas antaŭenigi la edukadon de nova generacio, kiu plenumas la kondiĉojn de la informa socio en sia evolunivelo kaj vivstilo.
Ĉi tiu kurso permesos al studentoj plifirmigi praktike sian scion pri la bazaj konstruaĵoj de la Pascal programlingvo. (el la programo de iu gimnazio por 2017)

Fine, mi decidis pasigi kelkajn horojn kaj skizi ekzemplon de "kiel krei simplan roboton por lernejanoj."

Sub la tranĉo estas kiel skribi alian simplan bot en Powershell kaj igi ĝin funkcii sen rethoko, blankaj IP-oj, dediĉitaj serviloj, deplojitaj virtualaj maŝinoj en la nubo, kaj tiel plu - sur regula hejma komputilo kun regula Vindozo.

TLDR: Alia enuiga artikolo kun gramatikaj kaj faktaj eraroj, nenio leginda, neniu humuro, neniuj bildoj.

Nenio nova estas en la artikolo, preskaŭ ĉio antaŭe verkita jam estis ĉe Habré, ekzemple en artikoloj Instrukcioj: Kiel krei robotojn en Telegramo и Telegram-bot por sistemadministranto.
Cetere, la artikolo estas intence superflua por ne ĉiufoje referenci al eduka literaturo. Ne estas referencoj al Gang 4, PowerShell Deep Dives aŭ, ekzemple, La 5 Kolonoj de la Bone Arkitektita Kadro de AWS en la teksto.

Anstataŭ antaŭparolo, vi povas salti

Bonvolu saltiEn 2006, Mikrosofto publikigis PowerShell 1.0 por la tiama Windows XP, Vista, kaj Server 2003. Kelkmaniere, ĝi anstataŭigis tiajn aferojn kiel cmdbat-skriptojn, vb-skriptojn, Windows Script Host kaj JScript.

Eĉ nun, PowerShell nur povas esti konsiderata kiel la sekva paŝo post la Logo-opcioj, anstataŭ la verŝajne ankoraŭ uzata Delphi (aŭ io pli malnova), malgraŭ la ĉeesto de bukloj, klasoj, funkcioj, MS GUI-vokoj, Git-integriĝo kaj tiel plu.

Powershell estas relative malofte uzata; vi nur povas renkonti ĝin en la formo de PowerShell Core, VMware vSphere PowerCLI, Azure PowerShell, MS Exchange, Dezirata Ŝtata Agordo, PowerShell Reta Aliro kaj dekduo pli malofte uzataj programoj kaj funkcioj. Eble li ricevos duan venton kun la liberigo WSL2, sed ĝi ne estas ĝuste.

Powershell ankaŭ havas tri grandajn avantaĝojn:

  1. Ĝi estas relative simpla, estas multe da literaturo kaj ekzemploj pri ĝi, kaj eĉ en la rusa, ekzemple, artikolo pri Foreach - el la libro PowerShell en profundo - pri la diferenco () kaj {}
  2. Li iras kun la redaktoro ISE, inkluzivita kun Vindozo. Tie estas eĉ ia erarserĉilo.
  3. Estas facile voki de ĝi komponantoj por konstrui grafikan interfacon.

0. Preparado.

Ni bezonos:

  • Vindoza komputilo (mi havas Windows 10)
  • Almenaŭ ia interreta aliro (per NAT ekzemple)
  • Por tiuj, kiuj havas limigitan aliron al telegramo - instalita kaj agordita freegate en la retumilo, en iuj malfacilaj kazoj, kune kun Symple DNS Crypt
  • Havante funkciantan telegramklienton sur via telefono
  • Kompreni la tre bazojn - kia variablo, tabelo, buklo estas.

Malfermitaj kaj legitaj artikoloj - Instrukcioj: Kiel krei robotojn en Telegramo и Telegram-bot por sistemadministranto

1. Ni kreu alian testbot.

Ĉar ĉiuj jam scias ĉi tion, kaj jam okazis, vi ankaŭ povas preterlasi ĝinKiel dirite en la supra artikolo - Unue, bot por Telegramo - ĝi ankoraŭ estas aplikaĵo kuranta sur via flanko kaj faranta petojn al la Telegram Bot API. Plie, la API estas klara - la bot aliras specifan URL kun parametroj, kaj Telegram respondas per JSON-objekto.

Rilataj problemoj: se en iu nekonata maniero vi prenas iun kodon de JSON-objekto kaj iel sendas ĝin por ekzekuto (ne intence), la kodo estos ekzekutita por vi.

La kreadprocezo estas priskribita en du artikoloj supre, sed mi ripetas: en telegramo ni malfermas kontaktojn, serĉas @botfather, diras al li /newbot, kreas bot Botfortest12344321, nomas ĝin Mynext1234bot, kaj ricevas mesaĝon kun unika ŝlosilo de la formo 1234544311:AbcDefNNNNNNNNNNNNNN

Prizorgu la ŝlosilon kaj ne fordonu ĝin!

Tiam vi povas agordi la bot, ekzemple, malpermesi aldoni ĝin al grupoj, sed en la unuaj paŝoj ĉi tio ne estas necesa.

Ni petu BotFather por "/mybot" kaj ĝustigu la agordojn se ni ne ŝatas ion.

Ni malfermu la kontaktojn denove, trovu @Botfortest12344321 tie (estas devige komenci la serĉon per @), alklaku "komenci" kaj skribu al la bot "/Gloro al la robotoj." La /-signo estas bezonata, citaĵoj ne necesas.
La bot, kompreneble, nenion respondos.

Ni kontrolu, ke la roboto estas kreita kaj malfermu ĝin.

api.telegram.org/bot1234544311:AbcDefNNNNNNNNNNNNNN/getMe
kie 1234544311:AbcDefNNNNNNNNNNNNNN estas la antaŭe ricevita ŝlosilo,
kaj ricevi ŝnuron kiel
{"ok":true,"result":{""}}

Ni havas la unuan sekretan frazon (ĵetono). Nun ni devas eltrovi la duan sekretan numeron - la ID de la babilejo kun la bot. Ĉiu babilejo, grupo ktp estas individua kaj havas sian propran numeron (foje kun minuso - por malfermitaj grupoj). Por ekscii ĉi tiun numeron, ni devas peti en la retumilo (fakte, ĝi tute ne estas necesa en la retumilo, sed por pli bona kompreno oni povas komenci per ĝi) la adreson (kie 1234544311:NNNNNNNNNN estas via ĵetono).

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

kaj ricevi respondon kiel

{"ok":true,"result":[{"update_id":...,... babilejo":{"id":123456789

Ni bezonas chat_id.

Ni kontrolu, ke ni povas skribi al la babilejo permane: voku la adreson de la retumilo

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

Se vi ricevas mesaĝon de bot en via babilejo, bone, vi transiras al la sekva etapo.

Tiel (per la retumilo) vi ĉiam povas kontroli ĉu estas problemoj pri la generado de ligiloj, aŭ ĉu io estas kaŝita ie kaj ne funkcias.

Kion vi bezonas scii antaŭ ol daŭrigi la legadon

Telegramo havas plurajn specojn de grupaj babilejoj (malferma, fermita). Por ĉi tiuj babilejoj, kelkaj el la funkcioj (ekzemple, id) estas malsamaj, kio foje kaŭzas kelkajn problemojn.

Ni supozu, ke estas la fino de 2019, kaj eĉ la heroo de nia tempo, la konata Man-Orkestro (administranto, advokato, specialisto pri informa sekureco, programisto kaj praktike MVP) Evgeniy V. distingas la variablon $i de tabelo, majstris maŝojn, rigardu en la venontaj du jaroj majstros Chocolatey, kaj tiam Paralela pretigo kun PowerShell и PorĈiu-Objekto Paralela ĝi venos.

1. Ni pensas pri tio, kion faros nia bot

Mi ne havis ideojn, mi devis pensi. Mi jam skribis bot-kajeron. Mi ne volis fari bot "kiu sendas ion ien." Por konektiĝi al Azure vi bezonas kreditkarton, sed de kie la studento ricevas ĝin? Notu, ke ĉio ne estas tiel malbona: la ĉefaj nuboj donas ian testperiodon senpage (sed vi ankoraŭ bezonas kreditkartan nombron - kaj ŝajnas, ke dolaro estos ŝuldita de ĝi. Mi ne memoras ĉu ĝi estis resendita poste.)

Sen AI ML ne estas tiom interese fari bot-malriĉan-poeton-teksiston.

Mi decidis fari bot, kiu memorigos min (aŭ ne min) pri anglaj vortoj el la vortaro.
Por eviti ludi kun la datumbazo, la vortaro estos konservita en tekstdosiero kaj ĝisdatigita permane.
En ĉi tiu kazo, la tasko estas montri la bazaĵojn de la laboro, kaj ne fari almenaŭ parte finitan produkton.

2. Provante kion kaj kiel unuafoje

Ni kreu dosierujon C:poshtranslate
Unue, ni vidu kian powershell ni havas, ni lanĉu ISE per start-run
powershell ise
aŭ trovi Powershell ISE en instalitaj programoj.
Post lanĉo, la kutima konata "ia redaktilo" malfermiĝos; se ne ekzistas tekstkampo, tiam vi ĉiam povas alklaki "Dosiero - krei novan".

Ni rigardu la version de powershell - skribu en la teksta kampo:

get-host 

kaj premu F5.

Powershell proponos konservi - "La skripto, kiun vi estas rulonta, estos konservita.", ni konsentas, kaj konservos la dosieron de powershell kun la nomo en C: poshtranslate myfirstbotBT100.

Post lanĉo, en la malsupra teksta fenestro ni ricevas datuman tabelon:

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

Mi havas 5.1 ion, tio sufiĉas. Se vi havas malnovan Vindozon 7/8 tiam ne gravas - kvankam PowerShell devos esti ĝisdatigita al versio 5 - ekz. instrukcioj.

Tajpu Get-Date en la komandlinio sube, premu Enen, rigardu la tempon, iru al la radika dosierujo kun la komando.
cd
kaj malplenigu la ekranon per la komando cls (ne, vi ne bezonas uzi rm)

Nun ni kontrolu kio funkcias kaj kiel - ni skribu eĉ ne la kodon, sed du liniojn, kaj provu kompreni kion ili faras. Ni komentu la linion kun get-host kun la simbolo # kaj aldonu iomete.

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

(Kio estas interesa estas, ke en la fallisto pri kodoformatado ĉe Habré estas du dekduoj da opcioj - sed Powershell ne estas tie. Dos estas tie. Perl estas tie.)

Kaj ni rulu la kodon premante F5 aŭ ">" de la GUI.

Ni ricevas la sekvan eligon:

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

Nun ni rigardu ĉi tiujn du liniojn kaj kelkajn interesajn punktojn, por ke ni ne revenu al ĉi tio estonte.

Male al Pascal (kaj ne nur), PowerShell mem provas determini kian tipon asigni al variablo; pli da detaloj pri tio estas skribitaj en la artikolo Eduka programo pri tajpado en programlingvoj
Tial, kreante $TimeNow-variablon kaj asignante al ĝi la valoron de la nuna dato kaj horo (Get-Date), ni ne devas zorgi tro pri kiaj datumoj estos tie.

Vere, ĉi tiu nescio eble doloros poste, sed tio estas por poste. Malsupre en la teksto estos ekzemplo.
Ni vidu kion ni ricevis. Ni ekzekutu (sur la komandlinio)

$TimeNow | Get-member

kaj akiri paĝon de nekomprenebla teksto

Ekzemplo de nekomprenebla teksto numero 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")...                                         

Kiel vi povas vidi, variablo de tipo TypeName: System.DateTime estis kreita kun amaso da metodoj (en la senco de tio, kion ni povas fari kun ĉi tiu variablo objekto) kaj propraĵoj.

Ni voku $TimeNow.DayOfYear — ni ricevas la numeron de la tago de la jaro.
Ni voku $TimeNow.DayOfYear | Get-Member - ni ricevas TypeName: System.Int32 kaj grupo de metodoj.
Ni voku $TimeNow.ToUniversalTime() - kaj ricevi la tempon en UTC

Elpurigilo

Kelkfoje okazas, ke necesas ekzekuti programon ĝis certa linio kaj vidi la staton de la programo en tiu momento. Tiucele, ISE havas Sencimigan funkcion - baskuli rompopunkton
Metu rompopunkton ien en la mezo, kuru ĉi tiujn du liniojn kaj vidu kiel aspektas la rompo.

3. Kompreni la interago kun la Telegram-bot

Kompreneble, eĉ pli da literaturo estis verkita pri interago kun la bot, kun ĉiuj getpush kaj tiel plu, sed la afero de teorio povas esti konsiderata laŭvole.

En nia kazo necesas:

  • Lernu sendi ion en korespondado
  • Lernu akiri ion el korespondado

3.1 Lerni sendi ion en korespondado kaj ricevi de ĝi

Eta kodo - parto 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

kaj en la Rusa Federacio ĉe ĉi tiu punkto ni ricevas la eraron Ne eblas konekti al la fora servilo.

Aŭ ni ne ricevas ĝin - dependas de la telekomunika operatoro kaj ĉu la prokurilo estas agordita kaj funkcianta
Nu, restas nur aldoni prokurilon. Bonvolu noti, ke uzi neĉifritan kaj ĝenerale fraŭdan prokurilon estas ege danĝera por via sano.

La tasko trovi funkciantan prokurilon ne estas tre malfacila - la plej multaj el la publikigitaj http-prokuriloj funkcias. Mi pensas, ke la kvina funkciis por mi.

Sintakso uzante prokurilon:

Invoke-WebRequest -Uri $URL4SEND -Proxy $MyProxy

Se vi ricevas mesaĝon en via babilejo kun bot, tiam ĉio estas en ordo, vi povas pluiri. Se ne, daŭrigu sencimigi.

Vi povas vidi, en kio fariĝas via $URL4SEND-ĉeno kaj provi peti ĝin en la retumilo, jene:

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

3.2. Ni lernis kiel skribi "ion" en babilejo, nun ni provu legi ĝin

Ni aldonu 4 pliajn liniojn kaj vidu kio estas ene tra | akiri-membron

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

La plej interesa afero estas provizita al ni

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

Ni vidu kio estas en ili:

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

Se ĉio funkcias por vi, vi ricevos longan linion kiel:

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

Feliĉe, en la antaŭe publikigita artikolo Telegram-bot por sistemadministranto ĉi tiu linio (jes, laŭ $MyMessageGet.RawContent | get-membro estas System.String), jam estis malmuntita.

4. Prilaboru tion, kion vi ricevas (ni jam scias kiel sendi ion)

Kiel jam skribite tie, la plej necesaj aferoj kuŝas en enhavo. Ni rigardu ĝin pli detale.

Unue, ni skribos kelkajn pliajn frazojn al la bot de la retinterfaco aŭ de la telefono

/message1
/message2
/message3

kaj trarigardu la retumilon la adreson formitan en la variablo $URLGET.

Ni vidos ion kiel:

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

Kio ĝi estas? Iu kompleksa objekto el tabeloj de objektoj enhavantaj fin-al-finan mesaĝidentigilon, babilidentigilon, sendantan identigilon kaj multajn aliajn informojn.

Tamen ni ne bezonas eltrovi "kia objekto ĉi tio estas" - parto de la laboro jam estas farita por ni. Ni vidu kio estas ene:

Legante ricevitajn mesaĝojn aŭ parton 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. Kion ni faru pri tio nun?

Ni konservu la rezultan dosieron sub la nomo myfirstbotBT105 aŭ kion ajn vi plej ŝatas, ŝanĝu la titolon kaj komentu la tutan jam skribitan kodon per

<#start comment 105 end comment 105#>

Nun ni devas decidi kie akiri la vortaron (nu, kie - sur disko en dosiero) kaj kiel ĝi aspektos.

Kompreneble, vi povas skribi grandegan vortaron ĝuste en la teksto de la skripto, sed ĉi tio estas tute ekster la afero.
Do ni vidu, per kio Powershell povas funkcii normale.
Ĝenerale, li ne zorgas kun kiu dosiero labori, ne gravas al ni.
Ni havas elekton: txt (vi povas, sed kial), csv, xml.
Ĉu ni povas rigardi ĉiujn?Ni vidu ĉiujn.
Ni kreu klason MyVocabClassExample1 kaj variablon $MyVocabExample1
Mi rimarkas, ke la klaso estas skribita sen $

iu kodo #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

Ni provu skribi ĉi tion en dosierojn uzante specimeno.

Iu kodo #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

- kaj ni ricevas eraron sur la linio Out-File -FilePath $MyFilenameExample01 -InputObject -Append $MyVocabExample2.

Li ne volas aldoni, ah-ah, kia domaĝo.

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

Ni vidu kio okazas. Bonega tekstvido - sed kiel eksporti ĝin reen? Ĉu mi enkonduku ian tekstajn apartigilojn, kiel komojn?

Kaj finfine vi ricevas "komo-separitaj valoroj (CSV) dosiero A ĈESU ATENDI.
#

$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 

Kiel facile videblas, MS ne aparte distingiĝas per sia logiko; por simila procedo, en unu kazo -FilePath estas uzata, en alia -Path.

Krome, en la tria dosiero malaperis la rusa lingvo, en la kvara dosiero montriĝis... nu, io okazis. #TIPO Sistemo.Objekto[] 00
# "Nombri"," Longo ", "LongLength", "Rango", "SyncRoot", "IsReadOnly", "IsFixedSize", "IsSynchronized"
#
Ni reverku ĝin iomete:

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

Ŝajnas, ke ĝi helpis, sed mi ankoraŭ ne ŝatas la formaton.

Mi precipe ne ŝatas, ke mi ne povas rekte meti liniojn de objekto en dosieron.
Cetere, ĉar ni komencis skribi al dosieroj, ĉu ni povas komenci konservi protokolon de lanĉo? Ni havas tempon kiel variablon, ni povas agordi la dosiernomon.

Vere, ankoraŭ estas nenio por skribi, sed vi povas pensi pri kiel plej bone turni la ŝtipojn.
Ni provu xml nuntempe.

Iuj 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

Eksporti al xml havas multajn avantaĝojn - legeblecon, eksportadon de la tuta objekto, kaj ne bezonas fari renverson.

Ni provu legi xml-dosieron.

Iom da legado el xml

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

Ni revenu al la tasko. Ni skribis testan dosieron, legas ĝin, la konserva formato estas klara, se necese, vi povas skribi apartan malgrandan dosiero-redaktilon por aldoni kaj forigi liniojn.

Mi memorigu vin, ke la tasko estis fari malgrandan trejnan roboton.

Laborformato: Mi sendas la komandon "ekzemplo" al la bot, la bot sendas al mi hazarde elektitan vorton kaj transskribon, kaj post 10 sekundoj sendas al mi tradukon kaj komenton. Ni scias kiel legi komandojn, ni ankaŭ ŝatus lerni kiel aŭtomate elekti kaj kontroli prokurojn, kaj restarigi mesaĝajn nombrilojn al forgeso.

Ni malkomenti ĉion antaŭe komentita kiel nenecesa, komentu la nun nenecesajn ekzemplojn per txt kaj csv, kaj konservu la dosieron kiel versio B106

Ho jes. Ni sendu ion denove al la bot.

6. Forsendo de funkcioj kaj pli

Antaŭ ol procesi la ricevon, vi devas krei funkcion por sendi "almenaŭ ion" krom testa mesaĝo.

Kompreneble, en la ekzemplo ni havos nur unu sendadon kaj nur unu prilaboradon, sed kio se ni bezonas fari la saman plurfoje?

Estas pli facile skribi funkcion. Do, ni havas variablon de tipo objekto $MyVocabExample4AsArray, legitan el la dosiero, en la formo de tabelo de eĉ du elementoj.
Ni iru legi.

Samtempe, ni traktos la horloĝon; ni bezonos ĝin poste (fakte, en ĉi tiu ekzemplo ni ne bezonos ĝin :)

Iu kodo #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
}

Kiel vi povas facile vidi, la funkcio vokas $MyToken kaj $MyChatID, kiuj estis malmola kodigitaj pli frue.

Ne necesas fari tion, kaj se $MyToken estas unu por ĉiu bot, tiam $MyChatID ŝanĝiĝos depende de la babilejo.

Tamen, ĉar ĉi tio estas ekzemplo, ni ignoros ĝin nuntempe.

Ĉar $MyVocabExample4AsArray ne estas tabelo, kvankam ĝi estas tre simila al unu, tiam vi ne povas simple preni ĝin peti ĝian longecon.

Denove ni devos fari ion nefareblan - paraŝuti ne laŭ la kodo - prenu ĝin kaj kalkulu

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

hazarda interesa trajto. Ni diru, ke ni volas ricevi 0 aŭ 1 (ni havas nur du elementojn en la tabelo). Kiam ni fiksas limojn 0..1, ĉu ni ricevos "1"?
ne - ni ne ricevos ĝin, ni havas specialan ekzemplon Ekzemplo 2: Akiru hazardan entjeron inter 0 kaj 99 Get-Random -Maksimume 100
Tial, por 0..1 ni devas agordi la grandecon 0..2, kun la maksimuma elemento nombro = 1.

7. Pretigo de envenantaj mesaĝoj kaj maksimuma vostolongo

Kie ni haltis pli frue? ni havas la ricevitan variablon $MyMessageGet
kaj $Content4Pars01 akirita de ĝi, pri kiu ni interesiĝas pri la elementoj de la Content4Pars01.result-tabelo

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

Ni sendu la bot /message10, /message11, /message12, /word kaj denove /word kaj /saluton.
Ni vidu, kion ni ricevis:

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

Ni trarigardu ĉion ricevitan kaj sendu respondon se la mesaĝo estis /vorto
la kazo de konstrukcio, kion iuj priskribas kiel if-elseif, estas nomita en powershell per ŝaltilo. Samtempe, la suba kodo uzas la -kodoklavon, kiu estas tute nenecesa kaj eĉ malutila.

Iu kodo #7.1

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

Ni rulu la skripton kelkajn fojojn. Ni ricevos la saman vorton dufoje por ĉiu ekzekutprovo, precipe se ni faris eraron en la efektivigo de hazarda.

Sed ĉesu. Ni ne sendis /vorton denove, do kial la mesaĝo estas procesita denove?

La vico por sendi mesaĝojn al la roboto havas finian longecon (100 aŭ 200 mesaĝojn, mi pensas) kaj devas esti forigita permane.

Ĉi tio kompreneble estas priskribita en la dokumentado, sed vi devas legi ĝin!

En ĉi tiu kazo, ni bezonas la parametron ?chat_id, kaj &timeout, &limit, &parse_mode=HTML kaj &disable_web_page_preview=true ankoraŭ ne estas bezonataj.

Dokumentado por telegram-api estas ĉi tie
Ĝi diras en blanka kaj angla:
Identigilo de la unua ĝisdatigo redonota. Devas esti pli granda je unu ol la plej alta inter la identigiloj de antaŭe ricevitaj ĝisdatigoj. Defaŭlte, ĝisdatigoj komenciĝas per la plej frua
nekonfirmita ĝisdatigo estas resenditaj. Ĝisdatigo estas konsiderata konfirmita tuj kiam getUpdates estas vokita per kompenso altaj ol ĝia update_id. La negativa ofseto povas esti specifita por preni ĝisdatigojn ekde -offset ĝisdatigo de la fino de la ĝisdatigvico. Ĉiuj antaŭaj ĝisdatigoj estos forgesitaj.

Ni rigardu:

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

Jes, kaj ni restarigos ĝin kaj reverkos la funkcion iomete. Ni havas du eblojn - transdoni la tutan mesaĝon al la funkcio kaj prilabori ĝin tute en la funkcio, aŭ doni nur la mesaĝon-identigilon kaj restarigi ĝin. Ekzemple, la dua aspektas pli simpla.

Antaŭe, nia "ĉiuj mesaĝoj" demandŝnuro aspektis

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

kaj ĝi aspektos kiel

$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 

Neniu malpermesas vin unue ricevi ĉiujn mesaĝojn, procesi ilin, kaj nur post sukcesa prilaborado peto nekonfirmita -> konfirmita.

Kial havas sencon voki konfirmon post kiam ĉiu pretigo finiĝis? Fiasko eblas meze de ekzekuto, kaj se por la ekzemplo de senpaga babilejo, manki unu mesaĝo estas nenio speciala, tiam se vi prilaboras ies salajron aŭ karttransakcion, la rezulto povas esti pli malbona.

Kelkaj pliaj linioj de kodo

$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. Anstata konkludo

Bazaj funkcioj - legado de mesaĝoj, restarigo de vosto, legado de dosiero kaj skribo al dosiero estas faritaj kaj montritaj.

Estas nur kvar aferoj por fari:

  • sendante la ĝustan respondon al peto en babilejo
  • sendante respondon al IUJ babilejo al kiu la bot estis aldonita
  • ekzekuti kodon en buklo
  • lanĉante bot de la vindoza planilo.

Ĉiuj ĉi tiuj taskoj estas simplaj kaj povas esti facile plenumitaj legante la dokumentadon pri parametroj kiel ekzemple
Set-ExecutionPolicy Senrestrikta kaj -ExecutionPolicy Bypass
ciklo de la formo

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

Dankon al ĉiuj, kiuj legis.

fonto: www.habr.com

Aldoni komenton