是否想要每天讓 Discord Bot 在早上時傳早安圖,晚上時傳水餃圖,如果是這樣,那要如何讓 Discord Bot 可以達成上述動作呢?
此篇教學將會介紹如何使用 tasks 語法,來製作可以固定時間執行或者一段時間執行的程式,來達成我們想要讓 Discord Bot 做的循環任務。
![Picture_1](https://hackmd.io/_uploads/BJbR2yxw2.png)
:::success
:book: **更多 Python Discord Bot 教學系列和程式範例**
https://github.com/smallshawn95/Python-Discord-Bot-Teach.git
:::
---
[TOC]
---
## 一、Tasks 基本語法:
下面的程式碼範例,是一個最基本的 Tasks 用法,功能是每秒輸出 "Hello, world!",可以參考下方表格來根據需求更改循環時間、運作次數,更多用法可參考 [discord.py API](https://discordpy.readthedocs.io/en/stable/ext/tasks/index.html)。
**@tasks.loop 傳入參數**
| 名稱 | 資料型態 | 說明 |
| :-----: | :-----: | :-----: |
| seconds 秒鐘 | float | 幾秒鐘執行一次 |
| minutes 分鐘 | float | 幾分鐘執行一次|
| hours 小時 | float | 幾小時執行一次 |
| time 時間 | datetime.time | 絕對時間執行一次 |
| count 次數 | int | 執行指定次數後退出 |
```python=
# 導入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))
```
![Picture_2](https://hackmd.io/_uploads/Sk17-YEw3.png)
## 二、Tasks 額外語法:
### 設定前後動作
添加 `@函式.before_loop` 可以在執行此函式前執行其他動作,添加 `@函式.after_loop` 可以在結束執行此函式後執行其他動作。
```python=
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")
```
![Picture_3](https://hackmd.io/_uploads/BklxWDXP2.png)
### 設定循環次數
在 `@tasks.loop()` 傳入 `count` 參數,可以設定函式的執行次數。
```python=
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")
```
![Picture_4](https://hackmd.io/_uploads/rkChGYVwh.png)
### 設定絕對時間
在 `@tasks.loop()` 傳入 `time` 參數,可以設定執行函式的絕對時間,如果要設定多個時間,只要儲存成串列傳入即可。
:::warning
:bell: 需要先導入 datetime 模組
```python
import datetime
```
:::
* 單個時間
```python=
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)
```
* 多個時間
```python=
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 教學,希望這篇教學有幫助到你們,目前筆者使用 tasks 來做每日報時功能、資料定時爬蟲、更改 Bot 狀態等等,讓我們一起把自己的 Discord Bot 擁有更多、更強大指令、功能吧!
如果此篇文章中有哪裡寫的不夠詳細,或者看不太懂意思,都歡迎到筆者的 Discord 伺服器中詢問、提供建議,目標讓 Python Discord Bot 教學系列文章可以篇篇清楚、完整,讓更多想持續學習的讀者可以獲得最正確的教學。
---
:::info
📢 **歡迎加入我的 Discord 伺服器**
https://discord.gg/Jtd3eVrFJs
:::
*Copyright © 2023 SmallShawn95. All rights reserved.*