Telegram Bot

10^11

目錄

  • TG 簡介(5 min)
  • 如何建立TG Bot(10 min)
  • Python 語法簡介(45 min)
  • 介紹TG Bot工具(60 min)
  • 實作練習(共60 min)

開始課程前,請先下載好

  1. VS code
  2. Telegram app(手機版一定要/電腦版看心情)

線上版本也可以

相信各位都看得懂英文

一定可以自行操作的

啾咪><

不重要的講師介紹

姓名:陳芊邑(10^11)

職位:社長x教學

網名:C.Y

綽號:千億姊姊、小清

興趣:休眠、跟數學玩

專長:壓線不遲到、成為瘋子

附註:我的精神狀態有點美麗,見諒一下

然後我很喜歡跟其他瘋資幹部們偷抱抱,但我是異性戀

這是我DC頭像

對這是情頭

Telegram 簡介

TG提倡自由與開放,其程式碼和 API 向所有人公開。透過直觀的操作介面,使用者能輕鬆與機器人互動,完成教學、遊戲、搜尋、提醒,甚至控制物聯網等功能。

這是我的課程介紹,對這是一串贛話:

Telegram 簡介

TG就是跟line很像的社交軟體,但它的隱私性非常強,

且bot的程式碼是完全開放的,

你可以把別人的程式碼修一下然後再上傳,跟DC Bot不太一樣,

然後它功能一堆

我簡單翻譯一下:

Telegram 簡介

 

  • 超大型群組(20萬人)
  • 高隱私加密(端對端加密)
  • 啊對所以這東西也是犯罪的溫床

 

如何建立TG Bot

  1. 下載電腦版&手機版TG Bot
  2. 請在 Telegram 搜尋欄搜尋 @botfather
  3. 輸入或點擊/start,可以得到所有指令

對我知道它很醜

但這就是生產機器人專用的帳號

它爸

如何建立TG Bot

4. 輸入 /newbot -> 輸入 Bot Name -> 輸入 Bot 的 username

 

*Emoji、圖片、貼圖都不能作為名稱 !

*Username 可用:

0-9、a-z、A-Z、-,

且要以 "bot" 作為結尾

如何建立TG Bot

5. 成功後,會回傳 API token,點一下就可以直接複製

*每個 Token 都對應到一個合法 Bot

*程式要有Token,Bot 才能夠被識別

如何建立TG Bot

6. 點選新建的 Bot 連結,並按下start

如何建立TG Bot

Python語法簡介

  • 基礎語法(速)
  • 資料結構(list、dictionary)
  • 函式(function)
  • 模組(module)
  • JSON
  • 套件(package)(補充)
  • 物件導向(補充)

大概會講這些

Python基礎語法

如果各大電神覺得這part贛話太多,請幫我指導一下你隊友

這part可能很快就能過去了

  • 輸出(output)&註解
  • 變數(variable)&運算子(operator)
  • 輸入(input)
  • 判斷式(if-else statement)
  • 迴圈(loop)

輸出&註解

print("easy")

#簡單的單行註解

"""

簡單的多行註解

"""

然後python不用寫分號

name="瘋子"
print(name)

變數&運算子

變數名稱=變數值,基本上概念你都學過了

型態 變數宣告 程式 執行結果
整數 int print(int(3.14)) 3
浮點數 float print(float(1)) 1.0
布林值 bool print(bool(1)) True

變數&運算子

算術運算子,基本上都是你學過的

運算子 說明 程式 執行結果
+ ​A=5+3 ​A=8
- A=5-3 A=2
* A=5*3 A=15
/ 浮點除法 A=5/2 A=2.5
// 整除 A=5//2 A=2
% 求餘 A=5%2 A=1
** 次方 A=5**2 A=25

變數&運算子

邏輯運算子,基本上都是你學過的

and 且:連接的兩個敘述都要正確才是 True

or 或:連接的兩個敘述只要有一個正確就是 True

not 非:否定一個敘述

啊丟,python不能用&&這種東西

哭了

變數&運算子

常用字串處理方法:

s1 = "楓資是瘋資也是瘋子"
print(s1)
#單行字串

zsisc = '''
    楓資

    是瘋資

    也是瘋子

'''
print(zsisc)
#多行字串

變數&運算子

常用字串處理方法:

print("Hello World".lower())
# 變成小寫
print("Hello World".upper())
# 變成大寫

str.split([分隔字])

將字串按照指定的分隔字分割

text="Hello World"
words=text.split()
print(words)
#['Hello','World']
print(words[0])
# Hello
print(words[1])
# World

date="2008-01-01"
parts=date.split('-')
print(parts)
# ['2008','01','01']

變數&資料型態

額外介紹一個好用的東西,f-string

name="瘋子"
print("楓資幹部都是",name,"很合理")
#輸出:楓資幹部都是 瘋子 很合理
name="瘋子"
print(f"楓資幹部都是{name}很合理")
##輸出:楓資幹部都是瘋子很合理
first=8
second=9
print(f"楓資幹部都是{first+second}很合理")
##輸出:楓資幹部都是17很合理

*使用單引號「'」與雙引號「"」

在Python都會被視為字串

輸入

變數=input([提示字串])

name=input("請輸入瘋子:")
print(f"{name}是怪人")
#輸入:吱吱 輸出:吱吱是怪人

判斷式

​1.if…

2.if…else…

3.if…elif…else…

4.巢狀 if

比c++多elif、冒號、縮排,少括號

chieh=87
if chieh>90:
    print("chieh is gami")
elif chieh>80:
    print("chieh is 甲殼類動物")
else:
    print("chieh is not human")

對,它沒有下放的問題,我可以不用跟我女鵝吵架了

這種時候就會突然覺得Python挺好的

判斷式

巢狀長這樣:

chieh=87
gami=8+9
if chieh>90:
    print("chieh is 企鵝")
else:
    if gami>87:
        print("gami is 怪人")
    elif gami>66:
        print("gami is 蜜獾")
    else:
        print("gami is 甲殼類動物")
        
#gami is 甲殼類動物

迴圈

跟c++的語法有差,但概念都一樣

for i in range(5):
    print("chieh is 企鵝")
# 輸出5次chieh is 企鵝
for i in range(2,10,2):
    print(i)
# 輸出2 4 6 8

1.for 變數 in 序列:

其中,序列中的值可以依序賦值給變數

多數時候會使用range()遍歷,當然也可以是list、dictionary之類的

range(起始值,結束值,公差)

迴圈

sum=0
i = 3
while i < 13:
    sum = sum + i
    i = i + 3
    print(i)
# 輸出 6 9 12 15

2.while 條件:

i=初始值

while i <= 終止值:

          程式

          i=i+-公差

*continue&break 在python的用法與c++同

分別是跳過當前迴圈繼續執行&跳出迴圈

Python資料結構

如果各大電神覺得這part贛話太多,請幫我指導一下你隊友

這part可能很快就能過去了

  • list
  • dictionary
  • tuple
  • set

Python資料結構

先來解釋資料結構的用途

Python資料結構

先來解釋資料結構的用途

如果說變數是一個盒子,我們把值丟在盒子裡

變數

Python資料結構

那麼,資料結構就是抽屜

變數

變數

變數

變數

變數

Python資料結構

我們把資料結構當成一種整理工具

將相關的資料整合

使程式碼更加簡潔、能更靈活的操作

進而進行資料分析

在製作專案上很常用

變數

變數

變數

變數

變數

Python資料結構

更生活一點的說法,就是把書分類,放在書櫃裡

重生文

帶球跑

穿越文

霸道總裁

強制愛

化學

物理

生物

數學

地科

笑鰲江湖

申鵰俠侶

田龍八部

路鼎記

血山飛狐

Python資料結構

很明顯他們應該這樣分配(沒有版權問題真好)

重生文

帶球跑

穿越文

霸道總裁

強制愛

化學

物理

生物

數學

地科

笑鰲江湖

申鵰俠侶

田龍八部

路鼎記

血山飛狐

網文

學術

仙俠

list

list的宣告方式&輸出

# 使用[] 宣告
empty_list=[]
anime_menu=["膽大黨","blue lock","哎咕島","夢幻島","我推"]
anime_like=[5,4,3,2,1]
print(anime_menu)
print(anime_like)

list

list的宣告方式&輸出

#使用list()將其它資料型態轉換成list
number_list=list(range(1,11))
print(number_list)
#輸出[1,2,3,4,5,6,7,8,9,10]

list

list的宣告方式&輸出

#使用條件式(list comprehensions)
even_number_list=[i for i in range(1,11) if i%2==0]
#符合條件的數字i加入到新的清單中。
print(even_number_list)

#使用迴圈
even_number_list=[]
for i in range(1, 11):
    if i % 2 == 0:
        even_number_list.append(i)
print(even_number_list)

#輸出[2,4,6,8,10]

list

使用index取用list的值

anime_menu=["膽大黨","blue lock","哎咕島","夢幻島","我推"]
anime_like=[5,4,3,2,1]
print(anime_menu[0])
print(anime_like[-1])
print(anime_menu[0:4:2])
print(anime_like[:])
print(anime_like[::-1])

5個print分別輸出?

list

使用index取用list的值

anime_menu=["膽大黨","blue lock","哎咕島","夢幻島","我推"]
anime_like=[5,4,3,2,1]
print(anime_menu[0])
#膽大黨
print(anime_like[-1])
#1
print(anime_menu[0:4:2])
#['膽大黨','哎咕島']
#[開始:結束:間隔] 
print(anime_like[:])
#[5,4,3,2,1]
print(anime_like[::-1])
#[1,2,3,4,5]

#[:n]->前n個元素
#[m:]->跳過前m個元素

list

使用index取用list的值(迴圈)

anime_menu=["膽大黨","blue lock","哎咕島","夢幻島","我推"]
anime_like=[5,4,3,2,1]
for i in range(5):
    print(anime_menu[i])
    
for i in anime_menu:
    print(i)
    
"""
輸出:
膽大黨
blue lock
哎咕島
夢幻島
我推
"""

list

介紹一些常用的method:

(看看就好)

number_list=[5,4,3,2,1]
number_list.append(6)
#新增值到list的最後->[5,4,3,2,1,6]
number_list.insert(2,7)
#在指定位置新增值->[5,4,7,3,2,1,6]
number_list.remove(7)
#移除指定值->[5,4,3,2,1,6]
del number_list[5]
#移除指定位置的值->[5,4,3,2,1]
number_list.sort()
#排序->[1,2,3,4,5]
number_list.reverse()
#反轉->[5,4,3,2,1]
number_list.pop()
#移除最後一個值->[5,4,3,2]
number_list2=number_list.copy()
#將list複製到list2
number_list.clear()
#清空所有值[]
print(len(number_list2))
#計算list2中的值的數量->4

.append()

.insert()

.remove()

del list[]

.reverse()

.pop()

.copy()

.clear()

len(list)

list

學完這些肯定會想:

那我們是不是可以把list合併呢?

list

Emmmm......我們先來看看list裡面的list

啊對,就是大家最喜歡的二維

anime_menu=[["膽大黨",5],["blue lock",4],["哎咕島",3],["夢幻島",2],["我推",1]]
print(anime_menu[0])
#輸出['膽大黨',5]
anime_menu[2][1]=5
#修改二維list中的值['哎咕島',5]

list

然後很直接了當的使用zip合併list

anime_menu=["膽大黨","blue lock","哎咕島","夢幻島","我推"]
anime_like=[5,4,3,2,1]
anime_menu_like=list(zip(anime_menu,anime_like))
print(anime_menu_like)
#輸出[('膽大黨',5),('blue lock',4),('哎咕島',3),('夢幻島',2),('我推',1)]

list

小延伸:

a=[1,2,3]
b=a
b.append(4)
print(a)

你們覺得這會輸出什麼?

list

小延伸:

a=[1,2,3]
b=a
b.append(4)
print(a)
#輸出[1,2,3,4]

list

為什麼?

a

[1,2,3]

list

理想上

a

[1,2,3]

b

[1,2,3]

複製

list

實際上

a

[1,2,3]

b

list

使用copy就解決了這個問題

a

[1,2,3]

b

a=[1,2,3]
b=a.copy()
b.append(4)
print(a)
#輸出[1,2,3]

Dictionary

每筆資料分別包含{"key":"value"}

key是唯一的,value可以是任何資料型態

Dictionary

舉例來說:

key value
動畫 Hunter × Hunter
作者 Yoshirin
主角 大傑
我推角 奇犽、沒下船那個
更新速度 超慢

Dictionary

你們也可以把自我介紹弄成這樣

但由於本人有點害羞所以還是算了

key value
動畫 Hunter × Hunter
作者 Yoshirin
主角 大傑
我推角 奇犽、沒下船那個
更新速度 超慢
anime={
    "動畫":"Hunter × Hunter",
    "作者":"Yoshirin",
    "主角":"大傑",
    "我推角":["奇犽","沒下船那個"],
    "更新速度":"超慢"
}

Dictionary

也可以這樣宣告

anime={
    "動畫":"Hunter × Hunter",
    "作者":"Yoshirin",
    "主角":"大傑",
    "我推角":["奇犽","沒下船那個"],
    "更新速度":"超慢"
}
anime=dict(
    動畫="Hunter × Hunter",
    作者="Yoshirin",
    主角="大傑",
    我推角=["奇犽","沒下船那個"],
    更新速度="超慢"
)

Dictionary

輸出方式:

anime={
    "動畫":"Hunter × Hunter",
    "作者":"Yoshirin",
    "主角":"大傑",
    "我推角":["奇犽","沒下船那個"],
    "更新速度":"超慢"
}
print(anime)
#輸出整個字典
#{'動畫':'Hunter × Hunter','作者':'Yoshirin','主角':'大傑','我推角':['奇犽','沒下船那個'],'更新速度':'超慢'}
print(anime["我推角"])
#['奇犽','沒下船那個']

Dictionary

使用方式跟list差不多

也是那幾種方法可以用

anime=dict(
    動畫="Hunter × Hunter",
    作者="Yoshirin",
    主角="大傑",
    我推角=["奇犽","沒下船那個"],
    更新速度="超慢"
)
anime["更新速度"]="有點慢"
print(anime["更新速度"])
#有點慢
anime.update({"更新速度":"有在更新了"})
print(anime["更新速度"])
#有在更新了
like=anime.pop("我推角")
print(like)
#['奇犽','沒下船那個']

Dictionary

如果想

從dict裡面抓取

key或value

該怎麼做?

anime=dict(
    動畫="Hunter × Hunter",
    作者="Yoshirin",
    主角="大傑",
    我推角=["奇犽","沒下船那個"],
    更新速度="超慢"
)
key=anime.keys()
print(key)
#dict_key(['動畫','作者','主角','我推角','更新速度'])
value=anime.values()
for value in anime.values():
    print(value)
"""
Hunter × Hunter
Yoshirin
大傑
['奇犽','沒下船那個']
超慢
"""

Dictionary

如果想

兩個一起取得呢?

anime=dict(
    動畫="Hunter × Hunter",
    作者="Yoshirin",
    主角="大傑",
    我推角=["奇犽","沒下船那個"],
    更新速度="超慢"
)

item=anime.items()
for key,value in item:
    print(f"key:{key},value:{value}")
"""
key:動畫,value:Hunter × Hunter
key:作者,value:Yoshirin
key:主角,value:大傑
key:我推角,value:['奇犽', '沒下船那個']
key:更新速度,value:超慢
"""

Dictionary

來做個小練習:

name_dic={
    "吱吱":"變態",
    "嘎米":"怪人",
    "葉子":"熬葉",
    "切魚":"女鵝",
    "起飛":"官配",
    "呱呱":"呱"
}

我在路上撿了來路不明的字典

我有點好奇,所以想要設計一個程式

有三個開發要求:

1.查詢此人特色

2.更新此人特色

3.印出此字典

4.結束程式

Dictionary

來做個小練習:

name_dic={
    "吱吱":"變態",
    "嘎米":"怪人",
    "葉子":"熬葉",
    "切魚":"女鵝",
    "起飛":"官配",
    "呱呱":"呱"
}

重視客戶UX體驗的人們,打算提供以下服務:

先詢問使用者選擇哪種操作

再問執行此操作的對象

若是使用者輸入的指令錯誤

可以另外告知他們

Dictionary

這是解答,盡量補藥複製喔啾咪

name_dic={
    "吱吱":"變態",
    "嘎米":"怪人",
    "葉子":"熬葉",
    "切魚":"女鵝",
    "起飛":"官配",
    "呱呱":"呱"
}

while True:
    print("1.查詢此人特色")
    print("2.更新此人特色")
    print("3.印出此字典")
    print("4.結束程式")

    choice=input("是時候做出選擇了:")
    if choice=="1":
        name=input("輸入名字:")
        if name in name_dic:
            print(f"{name}的特色是:{name_dic[name]}")
        else:
            print("他不是瘋子")
    
    elif choice=="2":
        name = input("輸入名字:")
        if name in name_dic:
            new=input(f"請輸入{name}的新特色:")
            name_dic[name]=new
            print(f"{name}的特色已更新為:{new}")
        else:
            print("他不是瘋子")
    elif choice=="3":
        for name,name_dic[name] in name_dic.items():
            print(f"{name}:{name_dic[name]}")
    elif choice=="4":
        print("結束")
        break
    else:
        print("眼睛不好要去看醫生")

Dictionary

我們還有很多課程

這只是個開始

Python函式

如果各大電神覺得這part贛話太多,請幫我指導一下你隊友

這part可能很快就能過去了

  • function
  • lambda
  • decorator

Python函式

function的基本架構

def zsisc(parameters1,parameters2):
    chyun=parameters1+parameters2
    return chyun
print(zsisc(8,9))

"""
def 函數名稱(參數1, 參數2, ...):
    函數程式碼
    return 返回值

"""

Python函式

匿名函式 lambda:

簡潔的好東西

r=int(input())
#匿名用法
print((lambda r:r*r*3.14)(r))
#不匿名用法
area=lambda r:r*r*3.14
print(area(r))
#輸出圓面積

Python函式

裝飾子Decorator:

裝飾器的本質是一個函數,它接收一個函數作為參數,並返回一個新的函數,從而動態地為原函數添加功能。

這聽起來有點難懂

我舉個栗子

Python函式

裝飾子Decorator:

簡單來說就是裝飾

腦子(函式)

書(裝飾)

+

Python函式

裝飾子Decorator:

簡單來說就是裝飾

會讀書的腦子(裝飾後函式)

Python函式

裝飾子Decorator:先來看看沒有語法蜜糖的情況

這種每用一次就要寫一次有點麻煩

import time
def timing(func):
    print("Start...")
    t1 = time.time()
    func()
    t2 = time.time()
    print("Elapsed time(secs):", t2 - t1)

def works():
    total = 0
    for i in range(10000):
        total += i
    print("total:", total)

timing(works)

Python函式

函式裡面包一個函式

import time
def timing(func):
    def wrapper():
        print("Start...")
        t1 = time.time()
        func()
        t2 = time.time()
        print("Elapsed time(secs):", t2 - t1)
    return wrapper

def works():
    total = 0
    for i in range(10000):
        total += i
    print("total:", total)

works = timing(works)
#將包裝過的函式再重新命名回原來被包裝的函式名稱
#為原始的函式加上了計時的功能, 同時又可以維持原始的函式名稱
works()

有沒有可能更簡潔?

Python函式

裝飾子Decorator:

import time
def timing(func):
    def wrapper():
        print("Start...")
        t1 = time.time()
        func()
        t2 = time.time()
        print("Elapsed time(secs):", t2 - t1)
    return wrapper

@timing
def works():
    total = 0
    for i in range(10000):
        total += i
    print("total:", total)

works()

用@就解決了

Python函式

作用域scope:

def zsisc(parameters1,parameters2):
    chyun=parameters1+parameters2
    return chyun
print(zsisc(8,9))
print(chyun)#報錯

global全域變數

local區域變數

Python函式

作用域scope:

def zsisc(parameters1,parameters2):
    global chyun
    chyun=parameters1+parameters2
    return chyun
print(zsisc(8,9))
print(chyun)

global全域變數

local區域變數

Python函式

Python模組

如果各大電神覺得這part贛話太多,請幫我指導一下你隊友

這part可能很快就能過去了

Python模組

什麼是module?

假設你今天穿越異世界

到了農業大國

結果發現那邊的攤販賣了一堆蔬果

但完全沒有分類

有強迫症的你會選擇?

Python模組

這就是module存在的意義

讓你依照功能整理你的程式

1.整理它

2.再丟一堆蔬果讓它更亂

聰明的你肯定會選1對吧?

對吧?

除非你有密集恐懼症

Python模組

假設你有一堆程式碼

你又很想要重複利用function?

那就依照功能把你家的程式碼打包成module,

你就不用一行一行看了

Python模組

什麼是模組(module):

是一個Python檔案,

每一個Python檔案被視為一個模組,

可以在程式中匯入其他Python模組,

模組就可以不斷地被其他程式再利用

Python模組

什麼是模組(module):

main.py

math.py

typing.py

Python模組

什麼是模組(module):

main.py

math.py

typing.py

Python模組

如何使用module?

使用import

1.引入單個模組

2.引入模組內某功能

Python模組

引入單個模組:

math是內建模組

floor()是取比該數小的最大整數

#語法結構
import <模組>
import math
print(math.floor(3.14))
# 3

Python模組

引入模組內的某些功能:

被import的對象可以是

子模組、函式、常數、類別

->可以import模組內任何東西

#語法結構
from <模組> import <模組內任何東西>
from <模組> import <子模組>,<函式>,<常數>,<類別>
from math import pi
print(pi)
# 3.141592653589793

Python模組

取別名:

也可以給它新的綽號

方便使用或辨認

import math as m
from math import pi as p
print(m.gcd(21,35))#最大公因數
print(p)

Python模組

常用的模組?

自己翻一下資料

1.time取時間

2.random取亂數

Python模組

time()常用的:

import time
print(time.time())
#顯示從 1970/1/1 00:00 到此刻的秒數
print(time.sleep(3))
#讓程式停止幾秒
print(time.ctime())
#顯示本地時間
print(time.strftime("%Y年%m月%d日 %H:%M:%S", time.localtime()))
#將時間轉換為可讀的字符串格式->string format time
#(指定格式,默認為當前時間)

Python模組

random()常用的:

import random
print(random.random())
#返回一個0到1之間的隨機浮點數[0.0, 1.0)
print(random.uniform(1, 10))
#返回a和b之間的隨機浮點數[a,b]
print(random.randint(1, 10))
#返回a和b之間的隨機整數[a,b]
print(random.randrange(1, 10, 2))
#返回指定範圍內的隨機整數(選擇1,3,5,7,9)
print(random.choice([1,2,3,4,5]))
#從序列中隨機選擇一個元素
print(random.choices(['a', 'b', 'c'], weights=[1, 2, 3], k=5))
#從序列中隨機選擇k個元素,允許重複選擇
#可以指定權重weights來影響選擇的機率
print(random.sample(range(1, 10), 3))
#從序列中隨機選擇k個不重複的元素

Python模組

Python套件

如果各大電神覺得這part贛話太多,請幫我指導一下你隊友

這part可能很快就能過去了

Python套件

如果說module是一個.py檔

那package就是很多個.py檔的資料夾

而__init__.py 是讓電腦將這個資料夾識別為 package,而不是普通的資料夾

package1

package2

Python套件

1.有效組織多個 module

package 之間命名隔離->

可以出現重複的變數/函數名稱,否則可能產生命名衝突

2.不需要重造輪子

自由下載/上傳寫好的 package

為什麼需要package?

Python套件

module v.s package?

Module Package
.py檔 __init__.py
+ 數個 .py 檔
可被其他 .py 引用 可被其他 .py 引用
定義 class, functions, variables 管理 Module

Python套件

package哪裡來?

1.自己寫:)

2.從 PyPI 或 GitHub 下載

3.自己寫好後上傳讓大家下載使用

Python套件

request通常用於網路爬蟲

是python常用的package

對成發maybe有用

可以參考一下

Json

如果各大電神覺得這part贛話太多,請幫我指導一下你隊友

這part可能很快就能過去了

Json

json是?

JavaScript Object Notation (JSON)

是一種資料交換的格式

易於人讀寫,同時也易於電腦分析與生成

Json

如何在python使用json?

1.import json

2.json.loads() json.dumps()

Json

在.py中python、json互換

import json

data ="""
{
    "楓資幹部": [
        {
            "姓名": "吱吱",
            "個性": "中二怪人",
            "習性": {
                "食物": "人",
                "每日睡眠時間": "24hr"
            }
        },
        {
            "姓名": "嘎米",
            "個性": "蜜獾",
            "習性": {
                "興趣": "愛錢"
            }
        }
    ]
}
"""

py_dict=json.loads(data)
#將json字串轉換為Python字典
new_json=json.dumps(py_dict,ensure_ascii=False, indent=4,sort_keys=True)
#將Python字典轉換為json字串
print(py_dict)
print(py_dict["楓資幹部"][0])
print(new_json)

Json

在.py中開啟&寫入json(記得開一個json檔)

import json
with open("file.json","r",encoding="utf-8") as f:
    data=json.load(f)
    #不加s->我們這次處理的是file不是string
print(data)
print(data.keys())
with open("file2.json","w",encoding="utf-8") as f2:
    json.dump(data,f2,ensure_ascii=False, indent=4)
    #將Python的資料結構(data)保存為json格式並寫入文件。

Json

檔案讀寫的部分再講一點

開啟模式:

'r':read 唯讀模式,只能讀,不能更改內容

'w':write 寫入模式(覆寫),會直接覆蓋原本檔案

'a':append 寫入模式(續寫),會從原本的檔案繼續寫下去,不會覆蓋掉

Json

這裡有淺顯易懂的解說(按圖片)

(雖然是全英但應該聽得懂)

物件導向

如果各大電神覺得這part贛話太多,請幫我指導一下你隊友

這part可能很快就能過去了

物件導向

什麼是物件導向?

物件導向(Object-Oriented programming,簡稱OOP)

一句話總結:

物件(Object)是類別(class)的實例(Instance)

物件導向

什麼是物件導向?

你想想,我們剛剛學的那些

看起來很難用在生活上吧?

誰會沒事走在路上看到一個東西就幫它寫dict或list?

物件導向就是把生活融入程式

用程式表達生活中會出現的東西

物件導向

有什麼好處?

1.開發時易於維護,可讀性提高

2.擴充功能時更加方便

3.使語意更為清晰

4.減少重複代碼

物件導向

在開始之前

先有個概念

類(Class):藍圖

類別屬性(Class Attribute):設計預定的材料

物件(Object):類的實例(Instance)

物件屬性(Object Attribute):實際製作的材料

物件導向

舉個栗子:

class Club_member:
    club_name="zsisc"
    def __init__(self,name,style,habit):
        self.name=name
        self.style=style
        self.habit=habit

cheer=Club_member("吱吱","中二怪人","從早睡到晚")
leaf=Club_member("葉子","葉氏集團總裁","不睡覺")
print(cheer.style)
print(leaf.habit)

物件導向

類別變數(Class variable)

實例變數(Instance variable)

吱吱

葉子

社團幹部

zsisc是類別變數

兩人都有各自的實例變數(名字、個性、習性)

補充:

物件導向

如果好奇TG Bot裡哪些是物件,哪些是類別,哪些是屬性,可以參考一下,等等上課疑惑的時候就拿出來翻

這是chat gpt弄出來的東西

Telegram Bot

對終於要講正事了

1.打開vs code

2.下載 python (extensions)

3.在終端(terminal)輸入:

pip install pyTelegramBotAPI

TG前置作業

檢查一下你的token

TG前置作業

https://api.telegram.org/bot<TOKEN>/getme

成功會回傳json檔案

token不小心洩漏出去怎麼辦?

TG前置作業

找BotFather,輸入指令/revoke,選擇想要更改的bot

我的token當然已經改掉了,不要想著偷講師的

Token?

TG前置作業

https://api.telegram.org/bot<TOKEN>/getUpdates

將自己 Bot 的 Token 替換掉 URL 的<TOKEN>

丟到google

然後你發訊息給你家bot,刷新網頁

好像有什麼東西改變了?

Token?

TG前置作業

你會發現裡面多了這些東西

- 你傳送訊息的時間

- 訊息來自哪個使用者

- 訊息在哪個聊天室被傳送

- 傳送的訊息內容

好像有點不太妙?

Token?

TG前置作業

所以你要保護好它

剛剛大家應該有注意到,

我們透過把 Token 輸入到 getMe、getUpdate 等 API 中,就能夠得到 Bot 的各種資訊

Token 就像 Bot 的身份證,API 藉此來辨別 Bot

PyTelegramBotAPI

TG前置作業

就是把剛剛大家體驗過的 getMe、getUpdates

還有其他很多 API 包裝成 Package 來使用

初始化:

TG前置作業

import telebot
TOKEN=""
bot=telebot.TeleBot(TOKEN,parse_mode=None)
#None也可以改成html或Markdown
#用來設定訊息的解析模式,影響你發送訊息時如何處理文字中的樣式
@bot.message_handler(commands=["start"])
def welcome(message):
    bot.reply_to(message,"hi")
bot.infinity_polling()

先確認一下有沒有連到:

TG前置作業

@bot.message_handler(commands=["start"])
def welcome(message):
    bot.reply_to(message,"hi")
bot.infinity_polling()

講解一下:

1.PyTelegramBotAPI 把傳入的訊息分類成很多種型別(Ex: text, audio, photo, video)等

2.message_handler有各種不同條件的過濾器,

用於篩選輸入訊息,讓函式拿到我們想要的訊息種類

3.Command 是一個特別的訊息,格式是:/[string]

TG前置作業

@bot.message_handler(commands=["start"])
def welcome(message):
    bot.reply_to(message,"hi")
bot.infinity_polling()

講解一下 bot.infinity_polling():

簡單來說就是可以讓 Bot 不斷地自動接收更新,

並且通知對應的函式有事件發生

TG前置作業

@bot.message_handler(commands=["start"])
def welcome(message):
    bot.reply_to(message,"hi")
    bot.send_message(message.chat.id,f"hi")
bot.infinity_polling()

講解一下 reply_to() & send_message()

reply_to()

就跟我們平常傳訊息會使用的回覆一樣

TG前置作業

@bot.message_handler(commands=["start"])
def welcome(message):
    bot.reply_to(message,"hi")
    bot.send_message(message.chat.id,f"hi")
bot.infinity_polling()

講解一下 reply_to() & send_message()

send_message()是傳送訊息到指定的聊天室中

welcome() 接收聊天室的 message,

這個 message 帶有聊天室 ID的資訊

聊天室 ID讓 send_message() 知道對話發生在哪個聊天室中

TG前置作業

@bot.message_handler(commands=["start"])
def welcome(message):
    bot.reply_to(message,"hi")
    bot.send_message(message.chat.id,f"hi")
bot.infinity_polling()

講解一下 reply_to() & send_message()

reply_to() 因為回覆該訊息,所以接收 message

send_message() 因為要直接傳送訊息在聊天室,所以接收 message.chat.id

TG前置作業

接下來是大家期待已久的實作環節~

Telegram Bot

先講基礎一點的

初學者必學的echo bot:

TG基礎班

初學者必學的echo bot:

開發要求:

1./help:描述bot功能

2.接受你輸入的所有訊息,回覆相同的訊息

3.對特定語句有反應

eg.輸入:我愛IZCC四校聯合寒訓

     輸出:不要再業配了

TG基礎班

初學者必學的echo bot:

小提示:

1.可以用 message.text 來取得輸入訊息的字串

2.利用 @message_handler() 中的 filter(func)來實作

3.可以試看看使用lambda

TG基礎班

初學者必學的echo bot:

對我就是不讓你們複製,啾咪

TG基礎班

初學者必學的echo bot:

函數過濾器,判斷訊息是否要被接收

輸入聊天室的訊息會被 message_handler() 接收,送入 lambda 函式

不管傳入什麼訊息,都會被接收

TG基礎班

初學者必學的報時仔:

TG基礎班

開發要求:

初學者必學的報時仔:

TG基礎班

開發要求:

輸入/time 回傳目前時間

初學者必學的報時仔:

TG基礎班

小提示:

1.from datetime import datetime

2.datetime.now()可以取目前時間

3.strftime: 把結構化的 datetime 轉變成指定格式的字串

初學者必學的報時仔:

TG基礎班

除了運用我們已經會的簡單指令以外,來學點有趣的

TG基礎班

先來看如何下載使用者所傳送的照片

TG基礎班

@bot.message_handler(content_types=['photo'])
def handle_photo(message):
    file_id=message.photo[-1].file_id
    #取得解析度最高的照片
    #取得照片的 file_id
    #file_id 是 Telegram 的一個唯一標識符,用於獲取該檔案
    file_info=bot.get_file(file_id)
    #獲取檔案詳細信息,包括檔案的路徑、大小等
    downloaded_file=bot.download_file(file_info.file_path)
    #下載檔案
    with open("received_image.jpg", "wb") as new_file:
        new_file.write(downloaded_file)
        #檔案名稱可以根據需要任意修改(.PNG/.jpg)
        #"w"是write,"b"是二進位模式(binary mode)開啟檔案(如圖片、音訊等會需要使用)
    bot.reply_to(message, "圖片已接收並保存!")

簡單說,流程長這樣

TG基礎班

with open("received_image.jpg", "wb")

received_image.jpg(new_file)

創建

以二進位模式寫入資料

簡單說,流程長這樣

TG基礎班

downloaded_file

new_file.write(downloaded_file)

二進位數據(圖片內容)寫入

new_file

簡單說,流程長這樣

TG基礎班

檔案自動關閉

new_file

成功儲存檔案

再來看看如何將照片傳給使用者

有兩種方法:

TG基礎班

1.從本機上傳

2.以連結方式上傳

TG基礎班

從本機上傳照片

@bot.message_handler(commands=['send_photo'])
def send_photo_command(message):
    with open("檔名", "rb") as photo:
    #圖片不能被解釋成文字,使用r
        bot.send_photo(message.chat.id, photo, caption="描述圖片")

TG基礎班

以連結方式上傳照片

@bot.message_handler(commands=['send_photo'])
def send_photo_url(message):
    url = "檔案連結"
    bot.send_photo(message.chat.id, url, caption="描述圖片")
    #就是把中間換成url而已

TG基礎班

PhotoSize (class)使用:

想要獲取圖片信息?

TG基礎班

PhotoSize (class)使用:

想要獲取圖片信息?

@bot.message_handler(content_types=['photo'])
def handle_photo(message):
    photo=message.photo[-1]
    file_id=photo.file_id
    #唯一標識,用於下載圖片。
    unique_id=photo.file_unique_id
    #永久標識符(不同bot間保持一致)。
    width=photo.width
    #寬度(像素)
    height=photo.height
    #高度(像素)
    size=photo.file_size
    #檔案大小(bytes)
    
    #圖片信息回覆
    response=(
        f"圖片信息:\n"
        f"File ID: {file_id}\n"
        f"Unique ID: {unique_id}\n"
        f"尺寸: {width}x{height} 像素\n"
        f"檔案大小: {size / 1024:.2f} KB"
      # 1 KB = 1024 bytes
      # 以浮點數格式輸出,並保留小數點後兩位
    )
    bot.reply_to(message, response)

TG基礎班

file_unique_id跟file_id差在哪裡?

Emmmmmm.......

好像有哪裡怪怪的?

(無論是圖片、音訊、影片都適用)

TG基礎班

file_unique_id跟file_id差在哪裡?

file_id file_unique_id
定義 唯一標識 永久標識
用途 檔案下載和處理 檔案比對、
唯一性檢查
變化 不同 bot發送時可能不同 永久固定,不隨 bot 變化
下載文件 可以用於下載 無法用於下載
時效性 可能會失效 永久有效

TG基礎班

其實音訊也是類似原理:如何下載使用者傳出的音訊?

@bot.message_handler(content_types=['audio'])
def download_audio(message):
    file_info = bot.get_file(message.audio.file_id)
    downloaded_file = bot.download_file(file_info.file_path)

    #保存到本地
    with open(message.audio.file_name, 'wb') as audio_file:
        audio_file.write(downloaded_file)

    bot.reply_to(message, f"音訊已下載並儲存")

TG基礎班

其實語音也是類似原理:如何下載使用者傳出的語音?

把audio改成voice

把.mp3改成.ogg

TG基礎班

那影片呢?

改成video

改成.mp4

聽起來真不戳,對吧

那短影片呢?

對,沒錯,我備課備這裡的時候也很意外

telegram居然有短視頻這種東西?!(圓形影片)

改成video_note就行

TG基礎班

現在來教大家一個酷東西:傳送多個檔案

我們有了新工具:

from telebot.types import InputMediaPhoto

 

InputMediaPhoto(class)

TG基礎班

現在來教大家一個酷東西:傳送多個檔案

from telebot.types import InputMediaPhoto

@bot.message_handler(commands=['send_photos'])
def send_photos_group(message):
    
    media_group=[
        InputMediaPhoto(media=open("1.jpg","rb"), caption="第一張照片"),
        InputMediaPhoto(media=open("2.jpg","rb"), caption="第二張照片"),
        InputMediaPhoto(media=open("3.jpg","rb"), caption="第三張照片")
    ]

    bot.send_media_group(message.chat.id, media_group)

TG基礎班

再補充一點:

duration():影片和音訊->持續時長(秒)

length():影片的直徑(像素)

TG基礎班

TG Bot內建了很多有趣好玩的小工具

來介紹幾個

TG基礎班

dice功能:

@bot.message_handler(commands=['dice'])
def roll_dice(message):
    sent_message=bot.send_dice(message.chat.id, emoji='🎲')
    result=sent_message.dice.value  #骰子的結果
    time.sleep(5)
    bot.reply_to(message, f"你擲出了 {result}!")

TG基礎班

dice功能:

不只有骰子可以用,同樣的語法可以換不同動畫

大家可以玩看看

🎲 骰子(數字 1 到 6)

🎯 飛鏢(數字 1 到 6,1 表示命中靶心)

🏀 籃球(數字 1 到 5,5 表示投籃成功)

🎳 保齡球(數字 1 到 6)

⚽ 足球(數字 1 到 6)

🎰 老虎机(數字 1 到 64)

TG基礎班

poll投票功能:可以做成quiz測驗!

q="楓資最瘋的幹部是?"
opt=["嘎米", "吱吱", "葉子", "起飛", "咕嚕", "呱呱", "C.Y", "以上皆是"]
correct_answer_index=7
@bot.message_handler(commands=['quiz'])
def send_quiz(message):
    bot.send_poll(
        chat_id=message.chat.id,
        question=q,
        options=opt,
        is_anonymous=False,
        allows_multiple_answers=False
    )
    bot.send_message(message.chat.id, "請選擇正確的答案!")

@bot.poll_answer_handler()
def handle_poll_answer(poll_answer):
    user_id = poll_answer.user.id
    selected_option = poll_answer.option_ids[0] 
    # 因為不允許多選,每次只有一個選項
    is_correct = selected_option == correct_answer_index
    if is_correct:
        result = "恭喜你,答對了!"
    else:
        result = "抱歉,答案錯誤!"

    bot.send_message(user_id, result)

TG基礎班

poll投票功能:可以做成quiz測驗!

還有一些有趣的方式

像是時間戳設定、多選之類的

就不另外放範例了

但會給你們資料

TG基礎班

但你還有進階班的課哈哈

Telegram Bot

再講進階一點的

今天要讀哪本書

好煩惱啊

來問問bot好了

TG進階班

來製作讀書計畫小幫手叭!

TG進階班

開發要求:

1./help:讓使用者知道 Bot 有哪些指令可以使用

2./add<書>:將書加入book中,並回傳提示訊息給使用者

3./list:用print()將book中的書本全部印出來

4./read:隨機選擇book中的一種科目,並且回傳給使用者

5./import:將Json檔案匯入book

6./export:將存在book中的資料匯出成Json檔案

來製作讀書計畫小幫手叭!

TG進階班

小提示:

1.開始前先複習List和Json檔案讀寫!

2.用 random.choice() 來選擇 list 中的食物

3.記得book要用global

第一個希望大家都能寫出來

TG進階班

我們要避開"add ",所以要用4:

TG進階班

這個應該也該寫出來了(叭?

TG進階班

要判斷一下是不是list為空

TG進階班

用"w"寫入,中文的話也要注意ensure_ascii=False

TG進階班

記得因為book被重新賦值,系統會判定其為區域變數

所以要另外global一次

TG進階班

在這次實作中,我們使用全域變數 "book" 來儲存資料,

這會讓所有使用者的資料是共用的

若是想要讓每個使用者能夠保存自己的資料,

可以使用 Dictionary:

Key 是使用者名稱

Value 是使用者的書單列表

TG進階班

這個問題就留給有興趣的弟妹玩

TG進階班

Inline Keyboard:

TG進階班

Inline Keyboard,按鈕的玩法:

def gen_markup():
    markup = InlineKeyboardMarkup()
    markup.row_width = 1
    markup.add(InlineKeyboardButton('💕', callback_data="double"),
                InlineKeyboardButton('💖', callback_data="star"),
                InlineKeyboardButton('💘', callback_data="arrow"))
    return markup

@bot.message_handler(commands=['inline'])
def message_handler(message):
    bot.send_message(message.chat.id, "按鈕選擇", reply_markup=gen_markup())

@bot.callback_query_handler(func=lambda call:True)
def callback(call):
    player_choice=call.data
    if player_choice=="double":
        bot.reply_to(call.message,"double")
    elif player_choice=="star":
        bot.reply_to(call.message,"star")
    else:
        bot.send_message(call.message.chat.id,"arrow")

TG進階班

蛤?

啊如果我要弄兩個不同功能的按鈕怎麼辦?

call:call.data in ["double", "star","arrow"]
 #把call:True改掉就好

記得之前說的過濾作用嗎?

只要指定需要的過濾的訊息就好了

TG進階班

按完按鈕會覺得怪怪的?有按跟沒按好像一樣?

pop_message=f"你選的是{player_choice}"
    bot.answer_callback_query(call.id,pop_message,show_alert=True)

注重客戶UX的我們

肯定要來個方便的小東西來提醒他們對叭?

萬一有五星好評呢?XD

TG進階班

用按鈕實作一個猜拳bot:

TG進階班

用按鈕實作一個猜拳bot:

開發要求:

/game - 顯示出 Inline Keyboard,包含剪刀、石頭、布三個選項

使用者點選 Keyboard 後,Bot 要隨機選擇要出什麼

回傳使用者、Bot 分別出什麼,並且「平手」、「使用者贏」、「Bot 贏」三個情況要分別回傳不同訊息到聊天室中

TG進階班

別忘了要先import

TG進階班

這個一定要寫出來的

對叭?(懇切的眼神

TG進階班

gesture是為了方便取用才寫的list

TG進階班

要有兩個變數,分別表示bot跟player

TG進階班

再來要介紹的是ReplyKeyboardMarkup:

大家在跟bot father聊天的時候,

會發現有個加速溝通的神祕鍵盤

那個東西就被稱為回覆鍵盤

from telebot.types import KeyboardButton, ReplyKeyboardMarkup

TG進階班

就這個東西:

TG進階班

可以這樣使用:

@bot.message_handler(commands=['start'])
def send_welcome(message):
    keyboard = ReplyKeyboardMarkup(resize_keyboard=True,input_field_placeholder="請選擇一個選項",one_time_keyboard=True)
    #按鈕的寬度會根據內容的長度自動調整,節省螢幕空間
    #keyboard = ReplyKeyboardMarkup(resize_keyboard=True, row_width=2) 至多兩個按鈕一行
    button1 = KeyboardButton("吱吱好中二")
    button2 = KeyboardButton("吱吱是怪人")
    keyboard.add(button1, button2)
    bot.send_message(message.chat.id, "請選擇一個最合適的選項:", reply_markup=keyboard)
@bot.message_handler(func=lambda message: True)
def handle_message(message):
    if message.text == "吱吱好中二":
        bot.reply_to(message, "確實!")
    elif message.text == "吱吱是怪人":
        bot.reply_to(message, "雀食!")
    else:
        bot.reply_to(message, f"收到消息:{message.text}")

bot.infinity_polling()

TG進階班

最後再介紹一個酷東西:

location!!!

相信各位在探索telegram的路途上

會發現這東西居然有定位功能?!

對,我們來借用剛剛學到的鍵盤玩看看

TG進階班

location定位功能:傳送使用者位置

@bot.message_handler(commands=['location'])
def ask_for_location(message):
    location_button = KeyboardButton(text="發送我的位置", request_location=True)
    markup = ReplyKeyboardMarkup(row_width=1, resize_keyboard=True)
    markup.add(location_button)
    bot.send_message(message.chat.id, "請分享你的地理位置:", reply_markup=markup)

@bot.message_handler(content_types=['location'])
def handle_location(message):
    latitude = message.location.latitude
    longitude = message.location.longitude
    bot.send_message(message.chat.id, f"你的地理位置是:\n緯度: {latitude}\n經度: {longitude}")

TG進階班

location定位功能:傳送指定位置

@bot.message_handler(commands=['send_location'])
def send_location(message):
    latitude=25.07110660725248
    longitude=121.52090323406448
    bot.send_location(
        chat_id=message.chat.id,
        latitude=latitude,
        longitude=longitude
    )

TG進階班

恭喜各位結束實作教程,有什麼問題都可以問看看

(關愛的眼神)

Telegram Bot

補充教學

TG進階班

大家在週二的網頁前端似乎也學了點東西

有沒有可能跟bot一起用呢?

哼哼,當然有,講師來補充一下遊戲鑲嵌

TG進階班

直接跟大家分享步驟

詳細的資料在簡報後面給各位研究一下

TG進階班

1.準備一個HTML/JS(遊戲)檔案

2.上傳到GitHub Pages,獲取遊戲網址

3.在BotFather裡輸入指令/newgame

   並依指示傳送訊息

4.連接TG Bot程式

TG進階班

1.準備一個HTML/JS(遊戲)檔案

2.上傳到GitHub Pages,獲取遊戲網址

3.在BotFather裡輸入指令/newgame

   並依指示傳送訊息

4.連接TG Bot程式

TG進階班

連接TG Bot程式

#你的GitHub Pages遊戲網址
GAME_URL = ""
#遊戲按鈕
@bot.message_handler(commands=['game'])
def send_game(message):
    bot.send_game(message.chat.id, "game short name")

# 點擊遊戲按鈕回應
@bot.callback_query_handler(func=lambda call: True)
def game_callback(call):
    if call.game_short_name == "game short name":
        bot.answer_callback_query(callback_query_id=call.id, url=GAME_URL)
    else:
        bot.answer_callback_query(callback_query_id=call.id, text="遊戲未找到!")

TG進階班

GitHub Pages資料

terminalGitHub

Telegram Bot

設定一下privacy

TG點綴版

1.Enable Privacy mode:不會收到其他人訊息

    ->Bot 權限不大,要 mention、回覆這個 bot,Bot 才會收到

    ->預設

2.Disable Privacy mode:Bot 可以讀取輸入的所有訊息

TG的privacy有兩種模式:

TG點綴版

1.找到 Bot Father,輸入 /mybots 選擇你要設定的 Bot

2.依序點選 Bot Settings -> Group Privacy -> Turn off

TG的privacy有兩種模式:

TG點綴版

1.到bot資訊頁面

2.點擊加入群組

3.選擇你的小隊群組

4.開始轟炸你的群組

(如果發現你家bot怪怪的,請按下ctrl+C,拯救你們的群組

將你家bot加入群組:

Telegram Bot

有什麼bot

TG點綴版

用來過濾非真人使用者的互動型 bot,如:

@shieldy_bot
@Customize_Captcha_Bot

TG點綴版

狼人殺:

@werewolfbot

TG點綴版

聊天機器人:

@ChatGPTBot

 

TG點綴版

文件轉換器:

@newfileconverterbot

TG點綴版

TG點綴版

遊戲

TG點綴版

Spotify 下載機器人

@Spotify Downloader Bot

TG bot

By 愛錢成癡,嗜賭成癮