Skip to content

Commit fb69761

Browse files
committed
v1
0 parents  commit fb69761

File tree

9 files changed

+189
-0
lines changed

9 files changed

+189
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.env
2+
node_modules
3+
package-lock.json

Dockerfile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
FROM node:20.11.0-alpine
2+
3+
WORKDIR /app
4+
5+
COPY . .
6+
RUN npm i
7+
8+
CMD ["npm", "start"]

LICENSE.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2024 mmq88x <[email protected]>
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# DEXPrice-DCMonitor
2+
3+
> 這是一個使用 [DexScreener](https://docs.dexscreener.com/) API 監控價格的 Discord 機器人。
4+
> This is a Discord bot that monitors prices using the [DexScreener](https://docs.dexscreener.com/) API.
5+
6+
## 設置 Setup
7+
8+
`example.env` 更改為 `.env` 並修改裡面的內容
9+
Rename example.env to .env and modify its contents as follows:
10+
11+
中文
12+
13+
```py
14+
DISCORD_TOKEN="Your Token" # 填入你的 Discord bot token
15+
TARGET_CHANNEL_IDS="Your Channel ID" # 以',', ex: 123456789,987654321
16+
CHAIN="ethereum" # 詳細的名稱清單請參考 https://docs.dexscreener.com/api/reference
17+
PAIR_HASH="0x646946F0518c6Ba27f1B2C6b4387EC6035bC42e3" # 範例交易對,使用的是 "丹 - PFPAsia" 的非官方交易對
18+
UPDATE_FREQUENCY = 5000 # in milliseconds
19+
20+
# TASKs
21+
UPDATE_STATUS="on" # 讓機器人將價格反應在狀態上,"on" 開啟 or "off" 關閉
22+
BOARDCAST="off" # 讓機器人發送價格訊息到 "TARGET_CHANNEL_IDS" 指定的頻道,"on" 開啟 or "off" 關閉
23+
```
24+
25+
English
26+
27+
```py
28+
DISCORD_TOKEN="Your Token" # Fill in your Discord bot token
29+
TARGET_CHANNEL_IDS="Your Channel ID" # Separated by ',', e.g., 123456789,987654321
30+
CHAIN="ethereum" # For a detailed list of names, please refer to https://docs.dexscreener.com/api/reference
31+
PAIR_HASH="0x646946F0518c6Ba27f1B2C6b4387EC6035bC42e3" # Example pair hash for the unofficial "Dan - PFPAsia" pair
32+
UPDATE_FREQUENCY = 5000 # in milliseconds
33+
34+
# TASKs
35+
UPDATE_STATUS="on" # Enable or disable the bot's ability to reflect prices in status. Use "on" or "off".
36+
BOARDCAST="off" # Enable or disable the bot's ability to send price messages to the channels specified in "TARGET_CHANNEL_IDS". Use "on" or "off".
37+
```
38+
39+
## 執行 Run
40+
41+
之後使用 docker compose 一鍵啟動即可
42+
Afterwards, use Docker Compose to start the bot with a single command:
43+
44+
```sh
45+
docker compose up -d --build
46+
```
47+
48+
或使用 node 執行原始碼
49+
Alternatively, you can run the source code using Node:
50+
51+
```sh
52+
npm run start
53+
```

app.js

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
const { Client, GatewayIntentBits, ActivityType } = require('discord.js');
2+
const { fetchPrice } = require('./utils');
3+
4+
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
5+
const dotenv = require('dotenv');
6+
7+
dotenv.config()
8+
9+
TASK_QUEUE = []
10+
11+
const registTask = async () => {
12+
if (process.env.UPDATE_STATUS == 'on') {
13+
TASK_QUEUE.push(updateStatus);
14+
}
15+
16+
if (process.env.BOARDCAST == 'on') {
17+
TASK_QUEUE.push(boardcast);
18+
}
19+
}
20+
21+
const doTask = async () => {
22+
await TASK_QUEUE.forEach(async (task) => {
23+
await task();
24+
});
25+
}
26+
27+
const updateStatus = async () => {
28+
const price = await fetchPrice()
29+
client.user.setActivity(`$${price}`, { type: ActivityType.Watching })
30+
}
31+
32+
const boardcast = async () => {
33+
const price = await fetchPrice()
34+
35+
// send message to all channels from specific channel ids
36+
const channelIds = process.env.TARGET_CHANNEL_IDS.split(',');
37+
38+
for (const channelId of channelIds) {
39+
const channel = await client.channels.fetch(channelId);
40+
await channel.send(`丹 DAN Price: $${price}`);
41+
}
42+
}
43+
44+
client.on('ready', () => {
45+
client.user.setActivity('丹 DAN Price', { type: ActivityType.Watching })
46+
console.log(`Logged in as ${client.user.tag}!`);
47+
registTask();
48+
49+
setInterval(async () => {
50+
doTask();
51+
}, process.env.UPDATE_FREQUENCY);
52+
});
53+
54+
client.login(process.env.DISCORD_TOKEN);

docker-compose.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
version: '3.7'
2+
services:
3+
dexprice-dcmonitor:
4+
build: .
5+
image: dexprice-dcmonitor
6+
restart: unless-stopped

example.env

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# This is an example, using the unofficial uniswap pool of DAN.
2+
3+
DISCORD_TOKEN="Your Token"
4+
TARGET_CHANNEL_IDS="Your Channel ID" # Seperated by ',', ex: 123456789,987654321
5+
CHAIN="ethereum" # Detail: https://docs.dexscreener.com/api/reference
6+
PAIR_HASH="0x646946F0518c6Ba27f1B2C6b4387EC6035bC42e3"
7+
UPDATE_FREQUENCY = 5000 # in milliseconds
8+
9+
# TASKs
10+
UPDATE_STATUS="on" # on or off
11+
BOARDCAST="off" # on or off

package.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"name": "pricemonitor",
3+
"version": "1.0.0",
4+
"description": "DEXScreener monitor with Discord bot.",
5+
"main": "app.js",
6+
"scripts": {
7+
"start": "node app.js"
8+
},
9+
"author": "mmq88x <[email protected]>",
10+
"license": "MIT",
11+
"dependencies": {
12+
"discord.js": "^14.14.1",
13+
"dotenv": "^16.4.2"
14+
}
15+
}

utils.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
const fetchPrice = async () => {
2+
priceUsd = -1;
3+
4+
try {
5+
const response = await fetch(
6+
`https://api.dexscreener.com/latest/dex/pairs/${process.env.CHAIN}/${process.env.PAIR_HASH}`
7+
);
8+
const data = await response.json();
9+
priceUsd = data.pair.priceUsd;
10+
11+
} catch (error) {
12+
console.log(error);
13+
}
14+
15+
return priceUsd;
16+
}
17+
18+
module.exports = { fetchPrice };

0 commit comments

Comments
 (0)