7-9-րդ դասարանների դպրոցականների համար պարզ հեռագրային բոտի ձևանմուշ՝ օգտագործելով Powershell

Ընկերոջս հետ զրույցի ժամանակ հանկարծ իմացա, որ իրենց դպրոցի 8-10-րդ դասարանների երեխաներին ընդհանրապես ծրագրավորում չեն սովորեցնում։ Word, Excel և վերջ: Ոչ մի լոգո, նույնիսկ Պասկալ, նույնիսկ VBA Excel-ի համար:

Ես շատ զարմացա, բացեցի ինտերնետը և սկսեցի կարդալ.
Մասնագիտացված դպրոցի խնդիրներից է տեղեկատվական հասարակության պայմաններին համապատասխանող նոր սերնդի կրթությունը նպաստելը իր զարգացման մակարդակով և ապրելակերպով։
Այս դասընթացը ուսանողներին թույլ կտա գործնականում համախմբել իրենց գիտելիքները Pascal ծրագրավորման լեզվի հիմնական կառուցվածքների վերաբերյալ: (Որոշ գիմնազիայի 2017 թվականի ծրագրից)

Ի վերջո, ես որոշեցի մի քանի ժամ ծախսել և ուրվագծել «ինչպես ստեղծել պարզ բոտ դպրոցականների համար» օրինակ:

Ստորև բերված է պատմություն այն մասին, թե ինչպես կարելի է գրել ևս մեկ պարզ բոտ Powershell-ում և այն աշխատեցնել առանց վեբ-կապիկի, սպիտակ IP-ի, հատուկ սերվերների, ամպի մեջ տեղակայված վիրտուալ մեքենաների և այլն՝ սովորական Windows-ով սովորական տնային համակարգչի վրա:

TLDR. Եվս մեկ ձանձրալի հոդված՝ քերականական և փաստական ​​սխալներով, կարդալու ոչինչ չկա, հումոր չկա, նկարներ չկան:

Հոդվածում ոչ մի նոր բան չկա, նախկինում գրված գրեթե ամեն ինչ արդեն եղել է Habr-ում, օրինակ հոդվածներում Հրահանգներ. Ինչպես ստեղծել բոտեր Telegram-ում и Telegram բոտ համակարգի ադմինիստրատորի համար.
Ավելին, հոդվածը միտումնավոր ավելորդ է, որպեսզի ամեն անգամ չանդրադառնանք ուսումնական գրականությանը։ Տեքստում հղումներ չկան Gang 4-ի, PowerShell Deep Dives-ի կամ, ասենք, AWS Well-Architected Framework-ի 5 սյուների մասին:

Նախաբանի փոխարեն կարող եք բաց թողնել

Ազատ զգալ բաց թողնել2006 թվականին Microsoft-ը թողարկեց PowerShell 1.0-ը այն ժամանակվա Windows XP-ի, Vista-ի և 2003 Server-ի համար: Որոշ առումներով այն փոխարինեց այնպիսի բաներ, ինչպիսիք են cmdbat scripts, vb scripts, Windows Script Host-ը և JScript-ը:

Նույնիսկ հիմա PowerShell-ը կարելի է համարել միայն որպես հաջորդ քայլ Logo տարբերակներից հետո՝ Delphi-ի (կամ ավելի հին որևէ այլ բանի) փոխարեն, որը հավանաբար դեռ ինչ-որ տեղ օգտագործվում է, չնայած ցիկլերի, դասերի, գործառույթների, MS GUI զանգերի առկայությանը, Git ինտեգրումներ եւ այլն:

Powershell-ը օգտագործվում է համեմատաբար հազվադեպ, կարող եք հանդիպել միայն PowerShell Core, VMware vSphere PowerCLI, Azure PowerShell, MS Exchange, Desired State Configuration, PowerShell վեբ մուտք և մեկ տասնյակ կամ ավելի հազվադեպ օգտագործվող ծրագրեր և գործառույթներ: Երևի երկրորդ քամին կսկսի հեռանալիս WSL2, բայց դա հաստատ չէ։

Powershell-ն ունի երեք մեծ առավելություն.

  1. Դա համեմատաբար պարզ է, դրա մասին շատ գրականություն և օրինակներ կան, և նույնիսկ ռուսերեն, օրինակ, հոդված Foreach-ի մասին - գրքից: PowerShell-ը խորությամբ — ()-ի և {}-ի տարբերության մասին
  2. Նա գնում է խմբագրի հետ։ Ise, ներառված է Windows-ի հետ։ Այնտեղ նույնիսկ ինչ-որ կարգաբերիչ կա:
  3. Դրանից հեշտ է զանգահարել բաղադրիչներ գրաֆիկական ինտերֆեյս կառուցելու համար.

0. Պատրաստում.

Մեզ անհրաժեշտ կլինի.

  • Windows-ով համակարգիչ (ես ունեմ Windows 10)
  • Առնվազն մի տեսակ ինտերնետ հասանելիություն (օրինակ՝ NAT-ի միջոցով)
  • Նրանց համար, ովքեր ունեն սահմանափակ մուտք դեպի telegram - զննարկիչում տեղադրված և կազմաձևված freegate, որոշ բարդ դեպքերում Symple DNS Crypt-ի հետ միասին
  • Ձեր հեռախոսում աշխատող հեռագրային հաճախորդ ունենալը
  • Հասկանալով հենց հիմունքները՝ ինչ է փոփոխականը, զանգվածը, օղակը:

Բացել և կարդալ հոդվածներ - Հրահանգներ. Ինչպես ստեղծել բոտեր Telegram-ում и Telegram բոտ համակարգի ադմինիստրատորի համար

1. Եկեք ստեղծենք ևս մեկ թեստային բոտ:

Քանի որ բոլորն արդեն գիտեն սա, և դա արդեն տեղի է ունեցել, դուք նույնպես կարող եք բաց թողնել:Ինչպես նշված է վերը նշված հոդվածում - Առաջին հերթին, բոտ Telegram-ի համար. դա դեռ ձեր կողմից աշխատող հավելված է, որը հարցումներ է կատարում Telegram Bot API-ին: Ավելին, API-ն պարզ է՝ բոտը մուտք է գործում որոշակի URL՝ պարամետրերով, իսկ Telegram-ը պատասխանում է JSON օբյեկտով։

Առնչվող խնդիրներ. եթե ինչ-որ կերպ վերցնում եք կոդ JSON օբյեկտից և ինչ-որ կերպ ուղարկում եք այն կատարման (ոչ դիտավորյալ), ապա կոդը կկատարվի ձեզ համար:

Ստեղծման գործընթացը նկարագրված է վերը նշված երկու հոդվածներում, բայց ես կկրկնեմ՝ Telegram-ում բացեք կոնտակտները, փնտրեք @botfather-ը, ասեք նրան /newbot, ստեղծեք Botfortest12344321 բոտ, անվանեք այն Mynext1234bot և ստացեք հաղորդագրություն 1234544311:AbNNNNNNNNN ձևի եզակի բանալիով:

Հոգ տանել բանալին և մի հանձնեք այն:

Դուք կարող եք հետագայում կարգավորել բոտը, օրինակ՝ արգելել այն ավելացնել խմբերին, բայց դա անհրաժեշտ չէ առաջին քայլերում:

Եկեք հարցնենք BotFather-ին «/mybot» և կարգավորենք կարգավորումները, եթե ինչ-որ բան մեզ դուր չի գալիս:

Եկեք նորից բացենք կոնտակտները, այնտեղ գտնենք @Botfortest12344321 (անհրաժեշտ է որոնումը սկսել @-ով), սեղմել «սկսել» և գրել բոտին «/Glory to the robots»։ / նշանը պարտադիր է, չակերտները պարտադիր չեն:
Բոտը, իհարկե, ոչինչ չի պատասխանի։

Եկեք ստուգենք, որ բոտը ստեղծվել է, բացենք այն:

api.telegram.org/bot1234544311:AbcDefNNNNNNNNNNNNNN/getMe
որտեղ 1234544311:AbcDefNNNNNNNNNNNN-ը նախկինում ստացված բանալին է,
և մենք ստանում ենք այսպիսի տող
{"ok":true,"result":{""}}

Մենք ունենք առաջին գաղտնի արտահայտությունը (token). Այժմ մենք պետք է պարզենք երկրորդ գաղտնի համարը՝ չաթի ID-ն բոտի հետ։ Յուրաքանչյուր չաթ, խումբ և այլն անհատական ​​է և ունի իր համարը (երբեմն բաց խմբերի համար մինուս նշանով): Այս համարը պարզելու համար անհրաժեշտ է բրաուզերում (իրականում դա անհրաժեշտ չէ բրաուզերում, բայց ավելի լավ հասկանալու համար կարող եք սկսել դրանից) հասցեն (որտեղ 1234544311:NNNNNNNN-ը ձեր նշանն է).

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

և ստացեք այսպիսի պատասխան

{"ok":true,"result":[{"update_id":...,... զրուցել«:{«id»:123456789

Մեզ անհրաժեշտ է հենց chat_id:

Եկեք ստուգենք, որ մենք կարող ենք գրել չաթում ձեռքով. զանգահարեք հասցեն բրաուզերից

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

Եթե ​​ձեր չաթում հաղորդագրություն եք ստանում բոտից, լավ, դուք անցնում եք հաջորդ քայլին:

Այս կերպ (բրաուզերի միջոցով) դուք միշտ կարող եք ստուգել, ​​թե որտեղ են խնդիրները՝ արդյոք խնդիրներ ունեք հղումը ստեղծելու հետ, թե ինչ-որ բան ինչ-որ տեղ թաքնված է և չի աշխատում:

Այն, ինչ դուք պետք է իմանաք նախքան կարդալը շարունակելը

Telegram-ում խմբակային չաթերի մի քանի տեսակներ կան (բաց, փակ): Այս չաթերի համար որոշ գործառույթներ (օրինակ՝ id) տարբեր են, ինչը երբեմն որոշակի խնդիրներ է առաջացնում։

Ենթադրենք, որ 2019-ի վերջն է, և նույնիսկ մեր ժամանակների հերոսը, հայտնի Man-Orchestra-ն (ադմինիստրատոր, իրավաբան, infosec մասնագետ, ծրագրավորող և գործնականում MVP) Եվգենի Վ.-ն տարբերում է $i փոփոխականը զանգվածից, տիրապետում է ցիկլերին, և միգուցե մոտակա մի քանի տարիներին նա կտիրապետի Chocol-ին, իսկ հետո նույնիսկ Chocol-ին։ Զուգահեռ մշակում PowerShell-ով и ForEach-Object զուգահեռ այն կհասնի այնտեղ:

1. Մենք մտածում ենք, թե ինչ կանի մեր բոտը

Ես գաղափարներ չունեի, ուստի ստիպված էի մտածել: Ես արդեն գրել եմ բոտի նոթատետր։ Ես չէի ուզում ստեղծել բոտ, որը «ինչ-որ տեղ ինչ-որ բան է ուղարկում»: Azure-ին միանալու համար ձեզ հարկավոր է կրեդիտ քարտ, իսկ որտեղի՞ց դպրոցականը: Հարկ է նշել, որ ամեն ինչ այնքան էլ վատ չէ. հիմնական ամպերը անվճար տրամադրում են ինչ-որ փորձաշրջան (բայց ձեզ դեռ պետք է կրեդիտ քարտի համարը, և այն կգանձվի, կարծում եմ՝ մեկ դոլար: Չեմ հիշում, թե ավելի ուշ հետ է եկել):

Առանց AI ML-ի, bot-idiot-versifier պատրաստելն այնքան էլ հետաքրքիր չէ։

Ես որոշեցի ստեղծել բոտ, որն ինձ (կամ ոչ ինձ) կհիշեցնի բառարանից անգլերեն բառերը։
Տվյալների բազայի հետ խառնաշփոթությունից խուսափելու համար բառարանը կպահվի տեքստային ֆայլում և ձեռքով կլցվի:
Այս դեպքում խնդիրն այն է, որ դրսևորվի հիմքերը գործողության մեջ, և ոչ թե գոնե մասամբ պատրաստի արտադրանքը:

2. Առաջին անգամ ինչ և ինչպես փորձել

Եկեք ստեղծենք C:poshtranslate թղթապանակ
Նախ, եկեք տեսնենք, թե ինչպիսի powershell ունենք, գործարկենք ISE-ն start-run-ի միջոցով
powershell ise
կամ գտնեք Powershell ISE-ն տեղադրված ծրագրերում:
Գործարկումից հետո կբացվի սովորական ծանոթ «մի տեսակ խմբագիր». եթե տեքստային դաշտ չկա, միշտ կարող եք սեղմել «Ֆայլ — ստեղծել նոր»:

Եկեք նայենք powershell տարբերակին - գրեք տեքստային դաշտում.

get-host 

և սեղմեք F5:

Powershell-ը կառաջարկի պահպանել. «Այն սկրիպտը, որը պատրաստվում եք գործարկել, կպահպանվի», մենք համաձայն ենք և կպահենք C:poshtranslate ֆայլը powershell-ից անունով: myfirstbotBT100.

Գործարկումից հետո մենք կստանանք տվյալների աղյուսակ ստորին տեքստային պատուհանում.

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

5.1 բան ունեմ, հերիք է։ Եթե ​​ունեք հին Windows 7/8, ապա խնդիր չկա, չնայած PowerShell-ը պետք է թարմացվի 5-րդ տարբերակին, օրինակ՝ հրահանգներ.

Եկեք ստորև հրամանի տողում մուտքագրենք Get-Date, սեղմենք Enter, նայենք ժամը և հրամանով գնանք արմատային թղթապանակ:
cd
և մաքրեք էկրանը cls հրամանով (ոչ, ձեզ հարկավոր չէ օգտագործել rm)

Հիմա եկեք ստուգենք, թե ինչ և ինչպես է այն աշխատում. մենք նույնիսկ կոդ չենք գրելու, այլ երկու տող և կփորձենք հասկանալ, թե ինչ են անում: Եկեք մեկնաբանենք get-host-ի տողը # նշանով և մի փոքր ավելացնենք:

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

(Հետաքրքիրն այն է, որ Habr-ում կոդերի ձևաչափման բացվող ցանկն ունի երկու տասնյակ տարբերակ, բայց Powershell-ը չկա: Dos-ը կա: Perl-ն այնտեղ է):

Եվ գործարկեք կոդը՝ սեղմելով F5 կամ «>» GUI-ից:

Մենք ստանում ենք արդյունքը.

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

Հիմա եկեք նայենք այս երկու տողերին և մի քանի հետաքրքիր կետերին, որպեսզի հետո չանդրադառնանք դրան:

Ի տարբերություն Պասկալի (և ոչ միայն), PowerShell-ն ինքն է փորձում որոշել, թե ինչ տեսակ վերագրել փոփոխականին, այս մասին ավելի շատ մանրամասներ գրված են հոդվածում։ Ծրագրավորման լեզուներով մուտքագրման այբբենարան
Հետևաբար, ստեղծելով $TimeNow փոփոխական և դրան վերագրելով ընթացիկ ամսաթվի և ժամի արժեքը (Get-Date), մենք կարիք չունենք շատ անհանգստանալու, թե ինչ տեսակի տվյալներ կլինեն այնտեղ:

Ճիշտ է, այս անտեղյակությունը կարող է ավելի ուշ ցավ պատճառել, բայց դա ավելի ուշ: Տեքստում ներքևում կլինի օրինակ:
Տեսնենք, թե ինչ ենք ստացել։ Եկեք գործարկենք այն (հրամանի տողում)

$TimeNow | Get-member

և մենք ստանում ենք անհասկանալի տեքստի էջ

Անհասկանալի թիվ 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")...                                         

Ինչպես տեսնում եք, TypeName տիպի փոփոխական՝ System.DateTime ստեղծվել է մի շարք մեթոդներով (այն իմաստով, թե ինչ կարող ենք անել այս փոփոխական օբյեկտի հետ) և հատկություններով:

Եկեք զանգենք $TimeNow.DayOfYear — մենք կստանանք տարվա օրվա թիվը։
Եկեք զանգենք $TimeNow.DayOfYear | Get-Member - ստանում ենք TypeName: System.Int32 և մի խումբ մեթոդներ:
Եկեք զանգենք $TimeNow.ToUniversalTime() — և մենք ստանում ենք ժամանակը ըստ UTC-ի

Դեբյուգգեր

Երբեմն պատահում է, որ պետք է ծրագիր գործարկել մինչև որոշակի տող և տեսնել ծրագրի վիճակը այդ պահին։ Այս նպատակով ISE-ն ունի գործառույթ, որը կոչվում է Debug — toggle break point
Տեղադրեք ընդմիջման կետ ինչ-որ տեղ մեջտեղում, անցեք այս երկու տողերը և տեսեք, թե ինչպիսին է ընդմիջումը:

3. Հասկանալով փոխազդեցությունը Telegram բոտի հետ

Իհարկե, ավելի շատ գրականություն կա գրված բոտի հետ փոխազդեցության, բոլոր getpush-ների և այլնի մասին, բայց տեսության հարցը կարելի է դիտարկել ընտրովի:

Մեր դեպքում անհրաժեշտ է.

  • Սովորեք նամակագրության մեջ ինչ-որ բան ուղարկել
  • Սովորեք նամակագրությունից ինչ-որ բան ստանալ

3.1 Մենք սովորում ենք ինչ-որ բան ուղարկել նամակագրության և ստանալ դրանից

Մի փոքր կոդ - Մաս 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

իսկ Ռուսաստանի Դաշնությունում այս պահին մենք սխալ ենք ստանում «Հնարավոր չէ միանալ հեռավոր սերվերին»:

Կամ մենք չենք ստանում այն, դա կախված է օպերատորից և արդյոք վստահված անձը կազմաձևված է և աշխատում է
Դե, մնում է միայն վստահված անձ ավելացնել: Խնդրում ենք նկատի ունենալ, որ չգաղտնագրված և ընդհանրապես կեղծ պրոքսիների օգտագործումը չափազանց վտանգավոր է ձեր առողջության համար:

Աշխատող վստահված անձ գտնելու խնդիրն այնքան էլ դժվար չէ՝ հրապարակված http վստահված անձանց մեծ մասն աշխատում է։ Կարծում եմ, որ դա հինգերորդն էր, որն ինձ մոտ ստացվեց:

Շարահյուսություն վստահված անձի միջոցով.

Invoke-WebRequest -Uri $URL4SEND -Proxy $MyProxy

Եթե ​​դուք հաղորդագրություն եք ստացել բոտի հետ ձեր չաթում, ապա ամեն ինչ լավ է, կարող եք առաջ շարժվել: Եթե ​​ոչ, ապա շարունակեք վրիպազերծումը:

Դուք կարող եք տեսնել, թե ինչի է վերածվում ձեր $URL4SEND տողը և փորձեք այն պահանջել ձեր դիտարկիչում, այսպես.

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

3.2. Չաթում սովորել ենք «ինչ-որ բան» գրել, հիմա փորձենք կարդալ

Եկեք ավելացնենք ևս 4 տող և տեսնենք, թե ինչ կա ներսում |-ի միջոցով ստանալ անդամ

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

Ամենահետաքրքիրը մեզ տրամադրում է

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

Տեսնենք, թե ինչ կա դրանց մեջ.

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

Եթե ​​ամեն ինչ աշխատում է ձեզ համար, դուք կստանաք այսպիսի երկար տող.

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

Բարեբախտաբար, նախկինում հրապարակված հոդվածում Telegram bot համակարգի ադմինիստրատորի համար այս տողը (այո, ըստ $MyMessageGet.RawContent | get-member-ը System.String է), արդեն ապամոնտաժվել էր։

4. Մշակել այն, ինչ ստացել ենք (մենք արդեն գիտենք, թե ինչպես գոնե ինչ-որ բան ուղարկել)

Ինչպես արդեն գրված է այստեղ, ամենակարեւորը բովանդակության մեջ է։ Եկեք մանրամասն նայենք դրան:

Նախ, եկեք ևս մի քանի արտահայտություն գրենք բոտին վեբ ինտերֆեյսից կամ հեռախոսից

/message1
/message2
/message3

և եկեք դիտարկիչով նայենք հասցեն, որը ձևավորվել է $URLGET փոփոխականում:

Մենք կտեսնենք նման բան.

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

Սա ի՞նչ է։ Որոշ բարդ օբյեկտ օբյեկտների զանգվածից, որը պարունակում է վերջից մինչև վերջ հաղորդագրության նույնացուցիչ, չաթի նույնացուցիչ, ուղարկող նույնացուցիչ և շատ այլ տեղեկություններ:

Այնուամենայնիվ, մեզ պետք չէ պարզել, թե «ինչպիսի առարկա է սա», աշխատանքի մի մասն արդեն արված է մեզ համար: Տեսնենք, թե ինչ կա ներսում.

Ստացված հաղորդագրությունների կամ 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. Ի՞նչ պետք է անենք սրա հետ հիմա:

Պահպանեք ստացված ֆայլը myfirstbotBT105 անունով կամ ինչ ուզում եք, փոխեք վերնագիրը և մեկնաբանեք արդեն գրված ամբողջ ծածկագիրը։

<#start comment 105 end comment 105#>

Այժմ մենք պետք է որոշենք, թե որտեղից պետք է ստանանք բառարանը (լավ, որտեղ՝ ֆայլի սկավառակի վրա) և ինչպիսի տեսք կունենա այն:

Իհարկե, դուք կարող եք հսկայական բառարան լցնել հենց սցենարի տեքստի մեջ, բայց դա ամենևին էլ խնդիրը չէ:
Այսպիսով, եկեք տեսնենք, թե ինչ Powershell-ի հետ կարող է նորմալ աշխատել:
Իրականում, նրան չի հետաքրքրում, թե որ ֆայլի հետ աշխատի, և մենք հոգ ենք տանում:
Մենք ունենք ընտրություն՝ txt (հնարավոր է, բայց ինչու), csv, xml:
Կարո՞ղ ենք բոլորին նայել: Եկեք նայենք բոլորին:
Եկեք ստեղծենք MyVocabClassExample1 դաս և $MyVocabExample1 փոփոխական
Նշում եմ, որ դասը գրված է առանց $

որոշ կոդ #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

Փորձենք սա գրել ֆայլերում նմուշի.

Որոշ կոդ #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

— և մենք սխալ ենք ստանում Out-File -FilePath $MyFilenameExample01 -InputObject -Append $MyVocabExample2 տողում:

Չի ուզում ավելացնել, օ-օ, ինչ ամոթ է:

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

Տեսնենք, թե ինչ կլինի։ Հիանալի տեքստային տեսք, բայց ինչպե՞ս այն ետ արտահանել: Արդյո՞ք պետք է մուտքագրեմ որոշ տեքստային բաժանարարներ, ինչպիսիք են ստորակետները:

Եվ արդյունքում դուք ստանում եք «ստորակետով բաժանված արժեքների (CSV) ֆայլ» ԴԱԴԱՐԵՑԵՔ ՍՊԱՍԵԼ.
#

$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 

Ինչպես հեշտությամբ կարող եք տեսնել, MS-ն առանձնապես չի տարբերվել տրամաբանությամբ. Նմանատիպ ընթացակարգի համար մի դեպքում օգտագործվում է -FilePath, մյուս դեպքում՝ Path:

Բացի այդ, այս երրորդ ֆայլում ռուսաց լեզուն անհետացավ, չորրորդ ֆայլում ինչ-որ բան եղավ... դե, ինչ-որ բան եղավ։ #TYPE System.Object[] 00
# «Count», «Length», «LongLength», «Rank», «SyncRoot», «IsReadOnly», «IsFixedSize», «IsSynchronized»
#
Եկեք մի փոքր վերաշարադրենք.

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

Թվում էր, թե դա օգնեց, բայց ես դեռ չեմ սիրում ձևաչափը:

Ինձ հատկապես դուր չի գալիս, որ ես չեմ կարող օբյեկտից տողեր ուղղակիորեն ֆայլի մեջ դնել:
Ի դեպ, քանի որ սկսել ենք ֆայլեր գրել, գուցե սկսե՞նք գործարկման մատյան պահել։ Մենք ժամանակ ունենք որպես փոփոխական, գիտենք ինչպես սահմանել ֆայլի անունը:

Դեռևս գրելու ոչինչ չկա, բայց մենք կարող ենք մտածել, թե ինչպես լավագույնս պտտել տեղեկամատյանները:
Եկեք փորձենք xml-ն առայժմ:

Մի քիչ 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

XML-ի արտահանումը առավելություններից բացի այլ բան չունի՝ ընթեռնելիություն, ամբողջ օբյեկտի արտահանում և վերափոխման կարիք չկա:

Եկեք փորձենք կարդալ xml ֆայլը.

Որոշ ընթերցումներ xml-ից

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

Վերադառնանք խնդրին։ Մենք գրել և կարդացել ենք թեստային ֆայլ, պահպանման ձևաչափը պարզ է, անհրաժեշտության դեպքում կարող ենք գրել առանձին փոքր ֆայլի խմբագիր տողեր ավելացնելու և ջնջելու համար։

Հիշեցնեմ, որ խնդիր էր դրված փոքրիկ ուսումնական բոտ պատրաստելը։

Աշխատանքի ձևաչափը. Ես բոտին ուղարկում եմ «example» հրամանը, բոտն ինձ ուղարկում է պատահական ընտրված բառ և տառադարձում, իսկ 10 վայրկյան հետո ուղարկում է թարգմանություն և մեկնաբանություն: Մենք կարող ենք կարդալ հրամանները, բայց մենք դեռ պետք է սովորենք, թե ինչպես ավտոմատ կերպով ընտրել և ստուգել վստահված անձինք, ինչպես նաև վերականգնել հաղորդագրությունների հաշվիչները մոռացության:

Եկեք չմեկնաբանենք այն ամենը, ինչ նախկինում մեկնաբանվել էր որպես ավելորդ, եկեք մեկնաբանենք txt և csv օրինակները, որոնք ավելորդ են դարձել, և ֆայլը պահենք որպես B106 տարբերակ:

Օ, այո: Եկեք նորից մի բան ուղարկենք բոտին։

6. Ուղարկում գործառույթներից և այլն

Նախքան ընդունելությունը մշակելը, դուք պետք է ստեղծեք «գոնե ինչ-որ բան» ուղարկելու գործառույթ, բացի թեստային հաղորդագրությունից:

Իհարկե, օրինակում մենք կունենանք միայն մեկ առաքում և միայն մեկ վերամշակում, բայց ի՞նչ, եթե մեզ անհրաժեշտ լինի մի քանի անգամ անել նույն բանը:

Ավելի հեշտ է ֆունկցիա գրել: Այսպիսով, մենք ունենք $MyVocabExample4AsArray տիպի օբյեկտի փոփոխական, որը կարդացվում է ֆայլից, որպես երկու ամբողջ թվային տարրերի զանգված։
Եկեք գնանք կարդալ:

Միևնույն ժամանակ, եկեք զբաղվենք ժամացույցով, այն մեզ ավելի ուշ պետք կգա (փաստորեն, այս օրինակում այն ​​մեզ պետք չի լինի :)

Որոշ կոդ #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
}

Ինչպես հեշտությամբ կարող եք տեսնել, ֆունկցիան կանչում է $MyToken և $MyChatID, որոնք ավելի վաղ կոշտ կոդավորված էին:

Դա անելու կարիք չկա, և եթե $MyToken-ը նույնն է յուրաքանչյուր բոտի համար, ապա $MyChatID-ը կփոխվի՝ կախված չաթից։

Այնուամենայնիվ, քանի որ սա օրինակ է, մենք առայժմ անտեսելու ենք այն։

Քանի որ $MyVocabExample4AsArray-ը զանգված չէ, թեև այն շատ նման է մեկին, ապա չես կարող պարզապես գնալ և պահանջեք դրա երկարությունը:

Եվս մեկ անգամ մենք ստիպված կլինենք անել այն, ինչ մենք չենք կարող անել՝ վայրէջք կատարել ոչ ըստ ծածկագրի, վերցնել և հաշվել

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

պատահական հետաքրքիր առանձնահատկություն. Ենթադրենք, մենք ուզում ենք ստանալ 0 կամ 1 (մենք ունենք ընդամենը երկու տարր զանգվածում): 0..1 սահմանները դնելիս մենք կստանա՞նք «1»:
ոչ - մենք չենք ստանա, մենք ունենք հատուկ օրինակ Օրինակ 2. Ստացեք պատահական ամբողջ թիվ 0-ից 99-ի միջև Ստացեք-Պատահական - Առավելագույնը 100
Հետևաբար, 0..1-ի համար մենք պետք է չափը դնենք 0..2, մինչդեռ տարրի առավելագույն թիվը = 1:

7. Մուտքային հաղորդագրությունների մշակում և հերթի առավելագույն երկարություն

Որտե՞ղ ենք մենք ավելի վաղ մեկնել: մենք ունենք ստացված $MyMessageGet փոփոխականը
և դրանից ստացված $Content4Pars01, որից մեզ հետաքրքրում են Content4Pars01.result զանգվածի տարրերը։

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

Եկեք ուղարկենք բոտը /message10, /message11, /message12, /word և նորից /word և /բարև:
Տեսնենք, թե ինչ ենք ստացել.

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

Մենք կանցնենք այն ամենի միջով, ինչ ստացել ենք և պատասխան կուղարկենք, եթե հաղորդագրությունը եղել է /word
Կոնստրուկտի դեպքը, որը ոմանք նկարագրում են որպես if-elseif, կոչվում է powershell-ում անջատիչի միջոցով. Այնուամենայնիվ, ստորև բերված կոդը օգտագործում է -wildcard ստեղնը, որը բոլորովին ավելորդ է և նույնիսկ վնասակար:

Որոշ կոդ #7.1

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

Եկեք մի երկու անգամ գործարկենք սցենարը։ Յուրաքանչյուր կատարման փորձի ժամանակ մենք կստանանք նույն բառը երկու անգամ, հատկապես, եթե սխալվել ենք պատահական իրականացման ժամանակ:

Բայց կանգ առեք: Մենք նորից չուղարկեցինք /word, ուստի ինչու է հաղորդագրությունը նորից մշակվում:

Բոտին հաղորդագրություններ ուղարկելու հերթն ունի վերջավոր երկարություն (կարծում եմ՝ 100 կամ 200 հաղորդագրություն) և պետք է մաքրել ձեռքով։

Իհարկե, սա նկարագրված է փաստաթղթերում, բայց դուք պետք է կարդաք այն:

Այս դեպքում մեզ անհրաժեշտ է ?chat_id պարամետրը, և դեռ անհրաժեշտ չեն &timeout, &limit, &parse_mode=HTML և &disable_web_page_preview=true:

Փաստաթղթերի վերաբերյալ telegram api-ն այստեղ է
Այնտեղ պարզ անգլերենով գրված է.
Առաջին թարմացման նույնացուցիչը, որը պետք է վերադարձվի: Պետք է լինի մեկով ավելի, քան նախկինում ստացված թարմացումների նույնացուցիչների մեջ ամենաբարձրը: Լռելյայն, թարմացումները սկսվում են ամենավաղից
չհաստատված թարմացումները վերադարձվում են: Թարմացումը համարվում է հաստատված, հենց որ getUpdates-ը կանչվի an-ով փոխհատուցել ավելի բարձր քան դրա update_id-ը. Բացասական օֆսեթը կարող է սահմանվել թարմացումները ստանալու համար՝ սկսած -offset թարմացումից թարմացումների հերթի վերջից: Բոլոր նախորդ թարմացումները կմոռացվեն:

Եկեք նայենք.

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

Այո, և մենք կզրոյացնենք այն, մենք մի փոքր կվերագրենք գործառույթը: Մենք ունենք երկու տարբերակ՝ փոխանցել ամբողջ հաղորդագրությունը ֆունկցիային և այն ամբողջությամբ մշակել ֆունկցիայի մեջ, կամ փոխանցել միայն հաղորդագրության ID-ն և վերականգնել այն: Օրինակ, երկրորդը ավելի պարզ է թվում:

Նախկինում մեր «բոլոր հաղորդագրությունները» հարցման տողը այսպիսի տեսք ուներ.

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

և այն կունենա այսպիսի տեսք

$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 

Ոչ ոք ձեզ չի արգելում նախ ստանալ բոլոր հաղորդագրությունները, մշակել դրանք և միայն հաջող մշակումից հետո հարցումը չհաստատված -> հաստատված:

Ինչու՞ իմաստ ունի բոլոր մշակման ավարտից հետո զանգահարել հաստատում: Հնարավոր է, որ ինչ-որ բան ձախողվի կատարման կեսին, և եթե անվճար չաթ-բոտի օրինակի դեպքում մեկ հաղորդագրություն բաց թողնելը մեծ խնդիր չէ, եթե դուք մշակում եք ինչ-որ մեկի աշխատավարձը կամ քարտով գործարքը, արդյունքը կարող է ավելի վատ լինել:

Կոդի ևս մի քանի տող

$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. Եզրակացության փոխարեն

Հիմնական գործառույթները՝ հաղորդագրություններ կարդալը, հերթը վերականգնելը, ֆայլից կարդալը և ֆայլ գրելը ավարտված և ցուցադրված են:

Մնում է ընդամենը չորս բան անել.

  • ուղարկելով հարցումին ճիշտ պատասխանը չաթում
  • ուղարկելով պատասխան ՑԱՆԿԱՑԱԾ զրույցին, որտեղ ավելացվել է բոտը
  • կոդի կատարումը օղակում
  • Բոտի գործարկում windows-ի ժամանակացույցից:

Այս բոլոր առաջադրանքները պարզ են և հեշտությամբ կարող են իրականացվել՝ կարդալով այնպիսի պարամետրերի վերաբերյալ փաստաթղթերը, ինչպիսիք են
Set-ExecutionPolicy անսահմանափակ և -ExecutionPolicy շրջանցում
տեսակների ցիկլը

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

Շնորհակալություն բոլորին, ովքեր կարդացել են այսքանը:

Source: www.habr.com

Добавить комментарий