工作循環是一個裝飾器,可以在固定時間或固定間隔執行工作
包括但不限於抓取API、發訊息等等,也可以做與機器人完全不相干的事

設定

先引入tasks,該模組位於discord.ext下,所以可以與commands合併寫成

1
from discord.ext import commands, tasks

固定間隔

對一個函數使用裝飾器@tasks.loop()
括號內填入參數

  • hours
  • minutes
  • seconds
    可以不必三個都填,選擇需要的即可
1
2
3
@tasks.loop(hours=11, minutes=45, seconds=14)
async def myfunction():
# 內容

固定時間

固定時間需要引入datetime模組來進行操作
指定時區則需要pytz,或是用原生的時區

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import datetime
import pytz

# 指定時區 (tz是timezone的縮寫)
# 以下做法擇一即可
# 1
tz = datetime.timezone(timedelta(hours=8))
# 2
tz = pytz.timezone('Asia/Taipei')

# 創建一個陣列儲存需要的時間點,時區參數tzinfo指定為剛剛的tz
times = [
datetime.time(hour=8, tzinfo=tz),
datetime.time(hour=12, minute=30, tzinfo=tz),
datetime.time(hour=16, minute=40, second=30, tzinfo=tz)
]

# 裝飾器參數改為time
# 如果時間只有一個,也可以直接在這裡填入只有一項的陣列
@tasks.loop(time=times)
async def myfunction():
# 內容

啟動

on_ready()事件下面加上此段
如果先前已經有過這個事件函數了,也可以合併進去

1
2
3
@bot.event
async def on_ready():
函數名稱.start()

練習

1. 讓機器人每20秒在特定頻道說哈囉

1
2
3
4
@tasks.loop(seconds=20)
async def sayHi():
channel = await bot.fetch_channel(ID)
await channel.send('哈囉')

2. 把觸發條件改成特定時間

可以設定時間為下一分鐘就好

1
2
3
4
5
6
7
8
9
10
import datetime
import pytz

tz = pytz.timezone('Asia/Taipei')


@tasks.loop(time=[datetime.time(hour=18, minute=48, tzinfo=tz)])
async def sayHi():
channel = await bot.fetch_channel(ID)
await channel.send('哈囉')