เทมเพลตสำหรับบอทโทรเลขอย่างง่ายสำหรับเด็กนักเรียนเกรด 7-9 โดยใช้ Powershell

ในระหว่างการสนทนากับเพื่อน จู่ๆ ฉันก็ได้เรียนรู้ว่าเด็กเกรด 8-10 ในโรงเรียนไม่ได้รับการสอนการเขียนโปรแกรมเลย Word, Excel และทุกสิ่ง ไม่มีโลโก้ แม้แต่ Pascal หรือแม้แต่ VBA สำหรับ Excel

ฉันประหลาดใจมากเปิดอินเทอร์เน็ตและเริ่มอ่าน -
ภารกิจหนึ่งของโรงเรียนเฉพาะทางคือการส่งเสริมการศึกษาของคนรุ่นใหม่ที่ตรงตามเงื่อนไขของสังคมสารสนเทศในระดับการพัฒนาและการใช้ชีวิต
หลักสูตรนี้จะช่วยให้นักเรียนรวบรวมความรู้เกี่ยวกับโครงสร้างพื้นฐานของภาษาโปรแกรม Pascal ในทางปฏิบัติ (จากโครงการยิมเนเซียมบางแห่ง ปี 2017)

ในท้ายที่สุด ฉันตัดสินใจใช้เวลาสองสามชั่วโมงและร่างตัวอย่าง “วิธีสร้างบอทแบบง่ายๆ สำหรับเด็กนักเรียน”

ด้านล่างนี้คือวิธีการเขียนบอตง่ายๆ อีกตัวใน Powershell และทำให้มันทำงานได้โดยไม่ต้องใช้เว็บฮุค, IP สีขาว, เซิร์ฟเวอร์เฉพาะ, เครื่องเสมือนที่ใช้งานในระบบคลาวด์ และอื่นๆ บนพีซีที่บ้านทั่วไปที่มี Windows ปกติ

TLDR: บทความน่าเบื่ออีกบทความหนึ่งที่มีข้อผิดพลาดทางไวยากรณ์และข้อเท็จจริง ไม่มีอะไรให้อ่าน ไม่มีอารมณ์ขัน ไม่มีรูปภาพ

ไม่มีอะไรใหม่ในบทความนี้ เกือบทุกอย่างที่เขียนก่อนหน้านี้มีอยู่ในHabréแล้ว เช่นในบทความ คำแนะนำ: วิธีสร้างบอทใน Telegram и บอทโทรเลขสำหรับผู้ดูแลระบบ.
นอกจากนี้ บทความนี้ยังมีการจงใจซ้ำซ้อนเพื่อไม่ให้อ้างอิงถึงวรรณกรรมทางการศึกษาทุกครั้ง ไม่มีการอ้างอิงถึง Gang 4, PowerShell Deep Dives หรือเช่น 5 Pillars ของ AWS Well-Architected Framework ในข้อความ

แทนที่จะเป็นคำนำ คุณสามารถข้ามได้

รู้สึกอิสระที่จะข้ามในปี 2006 Microsoft เปิดตัว PowerShell 1.0 สำหรับ Windows XP, Vista และ Server 2003 ในขณะนั้น ในบางวิธี มันเข้ามาแทนที่สคริปต์ cmdbat, สคริปต์ vb, Windows Script Host และ JScript

แม้กระทั่งตอนนี้ PowerShell ยังถือเป็นขั้นตอนต่อไปหลังจากตัวเลือกโลโก้ แทนที่จะเป็น Delphi ที่อาจยังคงใช้อยู่ (หรือบางอย่างที่เก่ากว่า) แม้ว่าจะมีลูป คลาส ฟังก์ชัน การเรียก MS GUI การรวม Git เป็นต้น

Powershell ถูกใช้ค่อนข้างน้อย คุณสามารถพบมันได้ในรูปแบบของ PowerShell Core, VMware vSphere PowerCLI, Azure PowerShell, MS Exchange, การกำหนดค่าสถานะที่ต้องการ, การเข้าถึงเว็บ PowerShell และโปรแกรมและฟังก์ชันที่ไม่ค่อยได้ใช้งานอีกหลายสิบโปรแกรมหรือมากกว่านั้น บางทีเขาอาจจะได้รับลมครั้งที่สองเมื่อปล่อย WSL2แต่ก็ไม่เชิงว่า

Powershell ยังมีข้อดีที่สำคัญสามประการ:

  1. มันค่อนข้างง่ายมีวรรณกรรมและตัวอย่างมากมายเกี่ยวกับเรื่องนี้และแม้แต่ในภาษารัสเซียเช่นบทความเกี่ยวกับ Foreach - จากหนังสือ PowerShell เจาะลึก - เกี่ยวกับความแตกต่าง () และ {}
  2. เขาไปกับบรรณาธิการ ISEที่มาพร้อมกับวินโดวส์ มีแม้กระทั่งดีบักเกอร์บางชนิดอยู่ที่นั่น
  3. มันง่ายที่จะโทรจากมัน ส่วนประกอบสำหรับการสร้างส่วนต่อประสานกราฟิก.

0. การเตรียมการ

เราจะต้อง:

  • พีซี Windows (ฉันมี Windows 10)
  • อย่างน้อยก็มีการเข้าถึงอินเทอร์เน็ตบางประเภท (ผ่าน NAT เป็นต้น)
  • สำหรับผู้ที่จำกัดการเข้าถึงโทรเลข - ติดตั้งและกำหนดค่า freegate ในเบราว์เซอร์ ในบางกรณีที่ยากลำบาก ร่วมกับ Symple DNS Crypt
  • มีไคลเอนต์โทรเลขที่ใช้งานได้บนโทรศัพท์ของคุณ
  • ทำความเข้าใจพื้นฐาน - อะไรคือตัวแปร, อาเรย์, ลูป

เปิดอ่านบทความแล้ว - คำแนะนำ: วิธีสร้างบอทใน Telegram и บอทโทรเลขสำหรับผู้ดูแลระบบ

1. มาสร้างบอททดสอบตัวอื่นกันดีกว่า

เนื่องจากทุกคนรู้เรื่องนี้แล้วและได้เกิดขึ้นแล้ว คุณก็สามารถข้ามมันไปได้ตามที่ระบุไว้ในบทความด้านบน - ก่อนอื่น บอทสำหรับ Telegram - มันยังคงเป็นแอปพลิเคชันที่ทำงานอยู่ข้างคุณและทำการร้องขอไปยัง Telegram Bot API ยิ่งไปกว่านั้น API นั้นชัดเจน - บอทเข้าถึง URL ที่ระบุพร้อมพารามิเตอร์ และ Telegram ตอบสนองด้วยออบเจ็กต์ JSON

ปัญหาที่เกี่ยวข้อง: หากคุณนำโค้ดบางส่วนจากออบเจ็กต์ JSON ไปใช้ด้วยวิธีใดวิธีหนึ่งที่ไม่รู้จัก แล้วส่งไปเพื่อดำเนินการ (ไม่ได้ตั้งใจ) โค้ดนั้นจะถูกดำเนินการสำหรับคุณ

กระบวนการสร้างอธิบายไว้ในสองบทความด้านบน แต่ฉันทำซ้ำ: ในโทรเลขเราเปิดผู้ติดต่อ มองหา @botfather บอกเขา /newbot สร้างบอท Botfortest12344321 เรียกมันว่า Mynext1234bot และรับข้อความพร้อมคีย์เฉพาะของ แบบฟอร์ม 1234544311:AbcDefNNNNNNNNNNNNNN

ดูแลกุญแจให้ดีอย่าแจก!

จากนั้นคุณสามารถกำหนดค่าบอทได้ เช่น ห้ามเพิ่มลงในกลุ่ม แต่ในขั้นตอนแรกก็ไม่จำเป็น

ลองขอ BotFather สำหรับ “/mybot” และปรับการตั้งค่าหากเราไม่ชอบอะไรบางอย่าง

มาเปิดผู้ติดต่ออีกครั้ง ค้นหา @ Botfortest12344321 ที่นั่น (จำเป็นต้องเริ่มการค้นหาด้วย @) คลิก "เริ่มต้น" และเขียนถึงบอท "/Glory to the robots" ต้องมีเครื่องหมาย / ไม่จำเป็นต้องใส่เครื่องหมายคำพูด
แน่นอนว่าบอทจะไม่ตอบอะไรเลย

ตรวจสอบว่ามีการสร้างบอทแล้วเปิดขึ้นมา

api.telegram.org/bot1234544311:AbcDefNNNNNNNNNNNNNN/getMe
โดยที่ 1234544311:AbcDefNNNNNNNNNNNNNN เป็นคีย์ที่ได้รับก่อนหน้านี้
และรับสตริงเหมือน
{"ตกลง":true,"ผลลัพธ์":{""}}

เรามีวลีลับข้อแรก (โทเค็น) ตอนนี้เราต้องค้นหาหมายเลขลับที่สอง - ID ของการแชทกับบอท แต่ละแชท กลุ่ม ฯลฯ เป็นรายบุคคลและมีหมายเลขของตัวเอง (บางครั้งมีเครื่องหมายลบ - สำหรับกลุ่มเปิด) เพื่อที่จะค้นหาหมายเลขนี้ เราจำเป็นต้องขอที่อยู่ (โดยที่ 1234544311:NNNNNNNNNN เป็นโทเค็นของคุณเพื่อความเข้าใจที่ดีขึ้น) (โดยที่ XNUMX:NNNNNNNNNN เป็นโทเค็นของคุณ

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

และได้รับการตอบสนองเช่น

{"ตกลง":true,"ผลลัพธ์":[{"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 ที่รู้จักกันดี (ผู้ดูแลระบบ ทนายความ ผู้เชี่ยวชาญด้านความปลอดภัยของข้อมูล โปรแกรมเมอร์ และ MVP ในทางปฏิบัติ) Evgeniy V. แยกตัวแปร $i ออกจากอาร์เรย์ ได้เชี่ยวชาญลูปแล้ว ดูอีกสองสามปีข้างหน้าจะเชี่ยวชาญเรื่อง Chocolatey แล้วหลังจากนั้น การประมวลผลแบบขนานด้วย PowerShell и สำหรับแต่ละวัตถุขนานกัน มันจะมา

1. เราคิดว่าบอทของเราจะทำอะไร

ฉันไม่มีความคิดใด ๆ ฉันต้องคิด ฉันได้เขียนบอทโน๊ตบุ๊คแล้ว ฉันไม่อยากสร้างบอท “ที่ส่งอะไรบางอย่างไปที่ไหนสักแห่ง” หากต้องการเชื่อมต่อกับ Azure คุณต้องมีบัตรเครดิต แต่นักเรียนได้มาจากไหน ควรสังเกตว่าทุกอย่างไม่ได้แย่นัก: คลาวด์หลักให้ช่วงทดสอบบางประเภทฟรี (แต่คุณยังต้องมีหมายเลขบัตรเครดิต - และดูเหมือนว่าจะหักเงินหนึ่งดอลลาร์จากมัน ฉันจำไม่ได้ว่า มันถูกส่งคืนในภายหลัง)

หากไม่มี AI ML การสร้างบอท-นักกวีผู้น่าสงสารก็ไม่น่าสนใจนัก

ฉันตัดสินใจสร้างบอทที่จะเตือนฉัน (หรือไม่ใช่ฉัน) ถึงคำศัพท์ภาษาอังกฤษจากพจนานุกรม
เพื่อหลีกเลี่ยงการเล่นกับฐานข้อมูล พจนานุกรมจะถูกจัดเก็บไว้ในไฟล์ข้อความและอัปเดตด้วยตนเอง
ในกรณีนี้ งานคือการแสดงพื้นฐานของงาน ไม่ใช่สร้างผลิตภัณฑ์สำเร็จรูปบางส่วนเป็นอย่างน้อย

2. ลองอะไรและอย่างไรเป็นครั้งแรก

มาสร้างโฟลเดอร์ C:poshtranslate กันดีกว่า
ก่อนอื่น เรามาดูกันว่าเรามี PowerShell ประเภทใด มาเปิดใช้ ISE ผ่านการเริ่ม-รันกัน
PowerShell ISE
หรือค้นหา Powershell ISE ในโปรแกรมที่ติดตั้ง
หลังจากเปิดตัว "ตัวแก้ไขบางประเภท" ที่คุ้นเคยตามปกติจะเปิดขึ้น หากไม่มีช่องข้อความคุณสามารถคลิก "ไฟล์ - สร้างใหม่" ได้ตลอดเวลา

ลองดูเวอร์ชันของ PowerShell - เขียนในช่องข้อความ:

get-host 

และกด F5

Powershell จะเสนอให้บันทึก - "สคริปต์ที่คุณกำลังจะเรียกใช้จะถูกบันทึก" เราเห็นด้วยและบันทึกไฟล์จาก PowerShell ด้วยชื่อใน C: poshtranslate 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 (или что-то типа)

ทีนี้มาดูสองบรรทัดนี้และจุดที่น่าสนใจบ้างเพื่อที่เราจะไม่กลับมาทำเช่นนี้อีกในอนาคต

แตกต่างจาก Pascal (และไม่เพียงเท่านั้น) 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 - สลับจุดพัก
วางเบรกพอยต์ไว้ตรงกลาง ลากเส้นทั้งสองนี้แล้วดูว่าเบรกพอยต์มีลักษณะอย่างไร

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 | รับสมาชิกคือ 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) 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 

ดังที่คุณเห็นได้ง่าย MS ไม่ได้แยกแยะความแตกต่างจากตรรกะของมันเป็นพิเศษ สำหรับขั้นตอนที่คล้ายกัน ในกรณีหนึ่ง -FilePath จะถูกใช้ ในอีกกรณีหนึ่ง -Path

นอกจากนี้ในไฟล์ที่สามภาษารัสเซียหายไป ในไฟล์ที่สี่ปรากฎว่า... มีบางอย่างเกิดขึ้น #ประเภทระบบ.วัตถุ[] 00
# “นับ””ความยาว””ความยาวยาว””อันดับ””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 

กลับมาที่ภารกิจกันดีกว่า เราเขียนไฟล์ทดสอบ อ่านมัน รูปแบบการจัดเก็บข้อมูลชัดเจน หากจำเป็น คุณสามารถเขียนโปรแกรมแก้ไขไฟล์ขนาดเล็กแยกต่างหากเพื่อเพิ่มและลบบรรทัดได้

ฉันขอเตือนคุณว่างานคือการสร้างบอทฝึกหัดขนาดเล็ก

รูปแบบการทำงาน: ฉันส่งคำสั่ง “ตัวอย่าง” ไปยังบอท บอทจะส่งคำและการถอดเสียงที่เลือกแบบสุ่มมาให้ฉัน และหลังจากผ่านไป 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 Get-Random -Maximum 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 และ /hello
มาดูกันว่าเราได้อะไรบ้าง:

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

มาดูทุกอย่างที่ได้รับและส่งคำตอบหากข้อความคือ /word
กรณีของ build ซึ่งบางคนอธิบายว่าเป็น 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 ด้วย ชดเชย สูงกว่า กว่ามัน 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

งานทั้งหมดนี้เรียบง่ายและสามารถบรรลุผลสำเร็จได้อย่างง่ายดายโดยการอ่านเอกสารประกอบเกี่ยวกับพารามิเตอร์ต่างๆ เช่น
ตั้งค่า ExecutionPolicy ไม่ จำกัด และ -ExecutionPolicy Bypass
วงจรของแบบฟอร์ม

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

ขอบคุณทุกคนที่อ่าน

ที่มา: will.com

เพิ่มความคิดเห็น