這是一篇使用 discord.py 模組開發的 Discord Bot 進階教學文章。
是否想要讓 Discord Bot 在每天早上傳長輩早安圖呢?此篇教學將會介紹 tasks 計時器工具,這工具可以固定時間或者每隔一段時間執行程式,藉此實現想要讓 Discord Bot 做的循環任務。

00

歡迎加入筆者的 Discord 伺服器 點此加入

Python Discord Bot 教學文章和程式碼範例 點此前往


一、Tasks 基本語法:

下面的程式碼範例,是一個最基本的 Tasks 用法,功能是每秒輸出 “Hello, world!”,可以參考下方表格來根據需求更改循環時間、運作次數,更多用法可參考 discord.py API

@tasks.loop 傳入參數

名稱 資料型態 說明
seconds 秒鐘 float 幾秒鐘執行一次
minutes 分鐘 float 幾分鐘執行一次
hours 小時 float 幾小時執行一次
time 時間 datetime.time 絕對時間執行一次
count 次數 int 執行指定次數後退出
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 導入discord.ext模組中的tasks工具
from discord.ext import tasks, commands

class TaskBase(commands.Cog):
def __init__(self, bot: commands.Bot):
self.bot = bot
# 開始執行函式
self.hi.start()
self.start_time = time.time()

def cog_unload(self):
# 取消執行函式
self.hi.cancel()

# 定義要執行的循環函式
@tasks.loop(seconds = 1)
async def hi(self):
execution_time = int(time.time() - self.start_time)
print(f"{execution_time}sec: Hello, world!")

async def setup(bot: commands.Bot):
await bot.add_cog(TaskBase(bot))

01

二、Tasks 額外語法:

設定前後動作

添加 @函式.before_loop 可以在執行此函式前執行其他動作,添加 @函式.after_loop 可以在結束執行此函式後執行其他動作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class TaskAction(commands.Cog):
def __init__(self, bot: commands.Bot):
self.bot = bot
self.action.start()

@tasks.loop(seconds = 1)
async def action(self):
print("Action")
self.action.cancel()

# 執行函式前的動作
@action.before_loop
async def action_before(self):
print("Wait")
# 等待機器人上線完成
await self.bot.wait_until_ready()

# 結束執行函式後的動作
@action.after_loop
async def action_after(self):
print("Stop")

02

設定循環次數

@tasks.loop() 傳入 count 參數,可以設定函式的執行次數。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class TaskCount(commands.Cog):
def __init__(self, bot: commands.Bot):
self.bot = bot
self.count.start()
self.start_time = time.time()

# 循環三次,每五秒輸出執行第幾次
@tasks.loop(seconds = 5, count = 3)
async def count(self):
execution_time = int(time.time() - self.start_time)
print(f"{execution_time}sec: Count {self.count.current_loop}")

# 函式執行三次後要執行的動作
@count.after_loop
async def after_slow_count(self):
execution_time = int(time.time() - self.start_time)
print(f"{execution_time}sec: Count end")

03

設定絕對時間

@tasks.loop() 傳入 time 參數,可以設定執行函式的絕對時間,如果要設定多個時間,只要儲存成串列傳入即可。

🔔 需要先導入 datetime 模組

1
import datetime
  • 單個時間
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    class TaskTime(commands.Cog):
    # 臺灣時區 UTC+8
    tz = datetime.timezone(datetime.timedelta(hours = 8))
    # 設定每日十二點執行一次函式
    everyday_time = datetime.time(hour = 0, minute = 0, tzinfo = tz)

    def __init__(self, bot: commands.Bot):
    self.bot = bot
    self.everyday.start()

    # 每日十二點發送 "晚安!瑪卡巴卡!" 訊息
    @tasks.loop(time = everyday_time)
    async def everyday(self):
    # 設定發送訊息的頻道ID
    channel_id = 1021706869724684376
    channel = self.bot.get_channel(channel_id)
    embed = discord.Embed(
    title = "🛏 晚安!瑪卡巴卡!",
    description = f"🕛 現在時間 {datetime.date.today()} 00:00",
    color = discord.Color.orange()
    )
    await channel.send(embed = embed)
  • 多個時間
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    class TaskTimes(commands.Cog):
    # 設定整點執行一次函式
    every_hour_time = [
    datetime.time(hour = i, minute = 0, tzinfo = datetime.timezone(datetime.timedelta(hours = 8)))
    for i in range(24)
    ]

    def __init__(self, bot: commands.Bot):
    self.bot = bot
    self.every_hour.start()

    # 每小時發送報時訊息
    @tasks.loop(time = every_hour_time)
    async def every_hour(self):
    # 設定發送訊息的頻道ID
    channel_id = 1021706869724684376
    channel = self.bot.get_channel(channel_id)
    embed = discord.Embed(
    title = f"⏰ 現在時間【{datetime.time.hour()}】時",
    color = discord.Color.random()
    )
    await channel.send(embed = embed)

此次教學已經結束,感謝各位看完整篇文章,希望這篇教學有幫助到你們。目前筆者使用 tasks 計時器工具來做每日報時功能、資料定時爬蟲、更改 Bot 狀態等等,發揮自己的想像力和創造力,讓我們一起將自己的 Discord Bot 開發出更多、更有趣的指令、功能吧!