# PecuLab WEB3 LiveCoding (2022-06-09)
## Discord運作機制及機器人程式開發
### **前置作業**
>* [雙重身分驗證](https://support.discord.com/hc/zh-tw/articles/219576828-%E9%9B%99%E9%87%8D%E9%A9%97%E8%AD%89%E8%A8%AD%E5%AE%9A)
>* [Vscode Download](https://code.visualstudio.com/download)
>* `pip discord.py `
>
>
>* [**Discord Develope** -申請Token](https://discord.com/developers/applications)
>* 邀請你的discord bot 進入你的頻道
## 開始撰寫discord bot程式!
### 先建置基礎架構
> 
>* cmds-副程式放置區
>* core-屬性定義放置
>* pic-照片放置
>* setting.json-將資料存在json檔以方便提取
### 主程式 chat.py
```python=1
import discord
from discord.ext import commands
import json
import random
import os
with open('setting.json',mode = 'r',encoding='utf8') as jfile:
jdata = json.load(jfile)
intents = discord.Intents.default()
intents.members = True
#discord 1.5之更新
bot = commands.Bot(command_prefix="==",intents = intents)
@bot.event #bot有無開啟
async def on_ready():
print('>> Bot is online <<')
@bot.command()
async def load(ctx,extension):
bot.load_extension(f'cmds.{extension}')
await ctx.send(f'Loaded {extension} done.')
@bot.command()
async def unload(ctx,extension):
bot.unload_extension(f'cmds.{extension}')
await ctx.send(f'Un-Loaded {extension} done.')
@bot.command()
async def reload(ctx,extension):
bot.reload_extension(f'cmds.{extension}')
await ctx.send(f'Re-Loaded {extension} done.')
for filename in os.listdir("./cmds"):
if filename.endswith('.py'):
bot.load_extension(f'cmds.{filename[:-3]}')
if __name__ == "__main__":
bot.run(jdata["TOKEN"])
```
### setting.json
```json=1
{
"TOKEN": "",
"guild": "",
"Welcome_channel": "",
"Leave_channel": "",
"pic": [
"C:\\Users\\DC\\discord bot\\test_chat\\pic\\01.jpg",
"C:\\Users\\DC\\discord bot\\test_chat\\pic\\02.jpg",
"C:\\Users\\DC\\discord bot\\test_chat\\pic\\03.jpg",
"C:\\Users\\DC\\discord bot\\test_chat\\pic\\04.jpg"
],
"url_pic": [
"https://i.kfs.io/playlist/global/67074264v1/cropresize/600x600.jpg",
"https://i.imgur.com/zvhwqXl.png"
]
}
```
### event.py
[discord_event](https://discordpy.readthedocs.io/en/stable/api.html?highlight=event#event-reference)
```python=1
from ast import keyword
import discord
from discord.ext import commands
from core.classes import Cog_Extension
import json
with open('setting.json',mode = 'r',encoding='utf8') as jfile:
jdata = json.load(jfile)
class Event(Cog_Extension):
@commands.Cog.listener() #成員加入
async def on_member_join(self,member):
channel = self.bot.get_channel(int(jdata['Welcome_channel'])) #ID
await channel.send(f'{member} 歡迎你加入!') #DC回應
@commands.Cog.listener() #成員退出
async def on_member_remove(self,member):
channel = self.bot.get_channel(int(jdata['Leave_channel']))
await channel.send(f'{member} QQ有緣再相見:(')
@commands.Cog.listener() #關鍵字
async def on_message(self,msg):
keyword = ['apple','banana']
if msg.content in keyword and msg.author != self.bot.user:
await msg.channel.send('hi')
@commands.Cog.listener() #按貼圖獲得身分組
async def on_raw_reaction_add(self,data):
if data.message_id == 984082202205778021: #選擇訊息ID
if str(data.emoji) == '🦉':
guild = self.bot.get_guild(data.guild_id)#取得當前伺服器
role = guild.get_role(970685526040510524)#取得伺服器內指定身分組
await data.member.add_roles(role)
await data.member.send(f'你取得了{role}身分組') #私訊
@commands.Cog.listener() #按貼圖離開身分組
async def on_raw_reaction_remove(self,data):
if data.message_id == 984082202205778021: #選擇訊息ID
if str(data.emoji) == '🦉':
guild = self.bot.get_guild(data.guild_id)#取得當前伺服器
role = guild.get_role(970685526040510524)#取得伺服器內指定身分組
user = guild.get_member(data.user_id)
# 下面remove_roles無.member可調用所以需自行抓取使用者
await user.remove_roles(role)
await user.send(f'你失去了{role}身分組') #私訊
#處裡"指令"發生之錯誤 Error Handler
#也可做獨立"指令"的錯誤訊息(EP15 29:00)
@commands.Cog.listener()
async def on_command_error(self,ctx,error):
if isinstance(error,commands.errors.MissingRequiredArgument):
await ctx.send('記得輸入參數喔!')
elif isinstance(error,commands.errors.BadArgument):
await ctx.send('參數型態錯了啦!')
elif isinstance(error,commands.errors.CommandNotFound):
await ctx.send('沒有這個指令喔!')
else:
await ctx.send('發生錯誤,再注意一下哪錯了!')
def setup(bot):
bot.add_cog(Event(bot))
```
### react.py
```python=1
import discord
from discord.ext import commands
from core.classes import Cog_Extension
import random
import json
with open('setting.json',mode = 'r',encoding='utf8') as jfile:
jdata = json.load(jfile)
class React(Cog_Extension):
@commands.command() #本機端上傳隨機圖片
async def 本機圖片(self,ctx):
random_pic = random.choice(jdata['pic'])
pic = discord.File(random_pic)
await ctx.send(file=pic)
@commands.command() #網址上傳隨機圖片
async def 網路圖片(self,ctx):
random_pic = random.choice(jdata['url_pic'])
await ctx.send(random_pic)
def setup(bot):
bot.add_cog(React(bot))
```
### main.py
[嵌入式訊息製造器](https://cog-creators.github.io/discord-embed-sandbox/)
```python=1
import discord
from discord.ext import commands
from core.classes import Cog_Extension
import datetime
import random
class Main(Cog_Extension):
@commands.command() #機器人之延遲(秒→毫秒→四捨五入)
async def ping(self,ctx): #ctx=上下文
await ctx.send(f'{round(self.bot.latency*1000)}(ms)')
@commands.command() #做出內嵌訊息
async def em(self,ctx):
embed=discord.Embed(title="嗨大家好這是一隻柴犬", url="https://cdn.hk01.com/di/media/images/2889837/org/4ef07fed4a8836f3ed6df68bbfc7d0c9.jpg/nAAal3F-2QSZICGJCFefX31f_bD3NTZhM-WgQjPloEI?v=w1920", description="柴犬", color=0x2099b1)
embed.set_author(name="柴柴", url="https://cdn.hk01.com/di/media/images/2889837/org/4ef07fed4a8836f3ed6df68bbfc7d0c9.jpg/nAAal3F-2QSZICGJCFefX31f_bD3NTZhM-WgQjPloEI?v=w1920", icon_url="https://cdn.hk01.com/di/media/images/2889837/org/4ef07fed4a8836f3ed6df68bbfc7d0c9.jpg/nAAal3F-2QSZICGJCFefX31f_bD3NTZhM-WgQjPloEI?v=w1920")
embed.set_thumbnail(url="https://cdn.hk01.com/di/media/images/2889837/org/4ef07fed4a8836f3ed6df68bbfc7d0c9.jpg/nAAal3F-2QSZICGJCFefX31f_bD3NTZhM-WgQjPloEI?v=w1920")
embed.add_field(name="年紀", value="3", inline=False)
embed.add_field(name="體重", value="20", inline=False)
embed.set_footer(text="大家好")
await ctx.send(embed=embed)
@commands.command() #複誦訊息
async def sayd(self,ctx,*,msg):
await ctx.message.delete()
await ctx.send(msg)
@commands.command() #刪除N筆訊息
async def clean(self,ctx,num:int):
await ctx.channel.purge(limit = num+1)
def setup(bot):
bot.add_cog(Main(bot))
```
## 學習資料!
>* [Discord Api](https://discordpy.readthedocs.io/en/stable/index.html)
>* [Proladon Youtube](https://www.youtube.com/playlist?list=PLSCgthA1Anif1w6mKM3O6xlBGGypXtrtN)
>* [音樂機器人檔案](https://github.com/Raptor123471/DingoLingo)