# Discord.js-Framwork-Typescript
## 簡介與製作動機
此專案改寫自[xiaoxigua-1](https://github.com/xiaoxigua-1)的[Discord.js-Framwork](https://github.com/xiaoxigua-1/Discord.js-framework),這專案同時也是我正式開始Typescript旅程的第一步。當初因為Discord.js沒有指令處理器,讓我不是很想跨入Discord.js,後來感謝[xiaoxigua-1](https://github.com/xiaoxigua-1)介紹了他製作的[Discord.js-Framwork](https://github.com/xiaoxigua-1/Discord.js-framework),讓我可以不用苦惱指令處理器的撰寫,可以直接開始寫指令。
後來接觸到了TypeScript,發掘到TypeScript相較於Javascript,TypeScript還有強大的型別註記與語法提示,所以便將[xiaoxigua-1](https://github.com/xiaoxigua-1)的[Discord.js-Framwork](https://github.com/xiaoxigua-1/Discord.js-framework)稍微優化並改寫成此專案。
順便附上[Discord.js-Framwork](https://github.com/xiaoxigua-1/Discord.js-framework)專案的README:
* 單純隨便寫的
* 恩~~如果覺得好用ㄉ話歡迎使用?
* 寫得很爛別介意
## 下載方式:
```sh
git clone https://github.com/Kayxue/Discord.js-Framwork-Typescript.git
```
## 使用方式:
### 1.先以vscode打開專案資料夾
### 2.安裝模組:
輸入以下指令安裝專案所有所需模組:
```sh
#使用npm
npm i #安裝專案所需模組
npm install --global typescript #安裝TypeScript
#使用yarn
yarn #安裝專案所需模組
yarn global add typescript #安裝TypeScript
```
### 3.編輯設定檔:
打開`src/Config.ts`並編輯設定
```typescript=
export const prefix = ""; //你想要的機器人前綴
export const owner_id = ""; //機器人擁有者ID
export const token = ""; //機器人的token
export const youtubeapitoken = ""; //YoutubeAPIToken,若不使用音樂功能則免填
export const blacklist = []; //使用指令黑名單,將使用者ID填入後該使用者使用指令時將不會有反應
```
### 4.執行專案:
* ### 方法1:使用tsc編譯
打開終端機輸入:
```sh
tsc #編譯程式碼
cd dist #切換到dist資料夾(程式碼編譯結果輸出處)
node . #執行專案
```
* ### 方法2:使用ts-node直接執行
:::info
若未安裝ts-node請使用下面指令安裝:
```sh
#使用npm
npm install --global ts-node
#使用yarn
yarn global add ts-node
```
:::
打開終端機輸入:
```sh
cd src #切換到src資料夾(專案資料夾)
ts-node . #執行專案
```
## 指令與事件監聽器撰寫方式:
### 新增類別部分:
#### 1.在Command資料夾下新增`[檔名].ts`
#### 2.匯入模組:
```typescript=
import Commands from "../core/commands";
import { Client, Message } from "discord.js";
...
```
#### 3.宣告類別
```typescript=
class w extends Commands { //類別名稱可自取
}
```
#### 4.宣告匯出函數
```typescript=
export default function setup(bot: Client) {
//實例化類別,此例類別為w(bot必要傳入參數)classname非必要傳入(該cog名稱)
let commands = new w(bot, "classname")
/*指令與事件監聽器撰寫處*/
bot.AddCog(commands)
}
```
### 撰寫指令部分:
```typescript=
/*撰寫指令*/
let w2 = commands.command(async function w(msg: Message, ...text: string[]) {
await msg.channel.send(text.join(" "))
}, { aliases: ["ee", "ww"] })
/*發生錯誤處理*/
w2.error((msg:Message, error) => {
console.log(error)
msg.channel.send(error)
})
```
1. command函式第一個參數為該指令程式碼撰寫處,傳入型別為函式
2. command函式第一個參數之傳入參數部分:第一個傳入參數為Message物件,第二個以後之傳入參數則是指令參數
3. command函式第二個參數部分為指令相關資訊:
* `name`:型別為字串,指令名稱
* `aliases`:型別為字串陣列,指令別名
* `help`:型別為字串,完整指令幫助
* `brief`:型別為字串,簡短指令幫助
:::warning
**注意:**
command函式第一個傳入參數可為具名函式或匿名函式(含箭頭函式):
* 若**傳入具名函式**,指令相關資訊的**name欄位可留空**
* 若**傳入匿名函式**,指令相關資訊的**name欄位則必須填寫**,若無填寫該欄位,則**該指令將無法被載入、觸發**
* 若**傳入具名函式**,指令相關資訊的**name欄位也有填寫**,則該指令之**指令名稱為該指令相關資訊的name欄位值**
:::
:::info
**<類別實體之名稱>.bot**可以傳回機器人物件:
```typescript=
commands.command((msg: Message) => {
console.log(commands.bot.user.username) //在終端機中印出機器人名稱
}, { name: "botname" })
```
:::
### 撰寫指令群組部分:
```typescript=
/*宣告指令群組*/
let e = commands.group(async function wq(msg: Message) {
console.log(msg.content)
}, { aliases: ["ep", "qq"] })
/*撰寫指令群組錯誤處理*/
e.error(async function (msg: Message, error) {
msg.channel.send(error.toString())
})
/*撰寫指令群組指令*/
let r = e.command(async function rr(msg: Message, x: string) {
commands.is_owner(msg)
commands.bot
await msg.channel.send("e.r")
}, { aliases: ["ep", "qq"] })
/*撰寫指令群組指令錯誤處理*/
r.error((msg: Message, error) => {
msg.channel.send(error.toString())
})
/*撰寫指令群組指令*/
e.command(function ww(message: Message) {
message.member.voice.channel.join().then(voicechannel => {
let w = voicechannel.play(youtubedl("https://www.youtube.com/watch?v=jIpiLvkDIK8", { quality: 'highestaudio' }), { volume: 0.5 })
w.pause()
voicechannel.play(youtubedl("https://www.youtube.com/watch?v=7i2knHE7ofQ", { quality: 'highestaudio' }), { volume: 0.5 })
})
})
```
1. group函式的作用:宣告一個指令群組
2. group函式第一個參數為當該指令無輸入子指令時所執行之函式
3. group函式第二個參數部分為指令相關資訊:
* `name`:型別為字串,指令名稱
* `aliases`:型別為字串陣列,指令別名
* `help`:型別為字串,完整指令幫助
* `brief`:型別為字串,簡短指令幫助
4. group函式會傳回Group物件:
* Group.command函式用法:與上方command函式相同
:::warning
**注意!**
* Group**沒有Listener函式!** 您**無辦法在指令群組內建立事件監聽器!**
* group函式第一個傳入參數可為具名函式或匿名函式(含箭頭函式):
* 若**傳入具名函式**,指令群組相關資訊的**name欄位可留空**
* 若**傳入匿名函式**,指令群組相關資訊的**name欄位則必須填寫**,若無填寫該欄位,則**該指令群組將無法被載入、觸發**
* 若**傳入具名函式**,指令群組相關資訊的**name欄位也有填寫**,則該指令群組之**指令群組名稱為該指令群組相關資訊的name欄位值**
:::
### 撰寫事件監聽器部分:
```typescript=
/*撰寫事件監聽器*/
commands.listener(function message(message: Message) {
console.log(`on_message:${message.author.tag}:${message.content}`)
})
commands.listener((msg: Message) => {
console.log("OK")
}, { event: "message" })
```
1. listener函式第一個參數為該事件程式碼撰寫處,傳入型別為函式
2. listener函式第一個參數之傳入參數部分請查看[Discord.js 官方文件的client事件](https://discord.js.org/#/docs/main/stable/class/Client?scrollTo=channelCreate),因為不同client之事件會傳入不同參數,在此就不一一列舉
3. listener函式第二個參數部分為監聽事件相關資訊:
* `event`:型別為字串,事件名稱
:::warning
**注意:**
* 若**傳入具名函式**,監聽事件相關資訊的**event欄位可留空**
* 若**傳入匿名函式**,監聽事件相關資訊的**event欄位則必須填寫**,若無填寫該欄位,則**該事件函式將無法被觸發**
* 若**傳入具名函式**,監聽事件相關資訊的**event欄位也有填寫**,則該事件函式之**監聽事件名稱為監聽事件相關資訊的event欄位值**
:::
:::info
以此範例為例,該事件函式會在機器人偵測到有人發訊息時被觸發。當該事件被觸發時,函式會傳入Message物件,並且執行事件函式裡的內容(印出指定內容)
### 官方文件:
![](https://i.imgur.com/0HUF5om.png)
:::