first on gitea
This commit is contained in:
1 parent
27894dac21
commit
94bf054772
22 files changed
+4829
-4657
No files matched your search
+8
-8
@@ -1,8 +1,8 @@
|
|||||||
# Discord Bot Token — get yours at https://discord.com/developers/applications
|
# Discord Bot Token — get yours at https://discord.com/developers/applications
|
||||||
BOT_TOKEN=your_bot_token_here
|
BOT_TOKEN=your_bot_token_here
|
||||||
|
|
||||||
# Command prefix (default: !)
|
# Command prefix (default: !)
|
||||||
PREFIX=!
|
PREFIX=!
|
||||||
|
|
||||||
# Guild ID for test server (optional — used for dev utilities)
|
# Guild ID for test server (optional — used for dev utilities)
|
||||||
GUILD_ID=your_guild_id_here
|
GUILD_ID=your_guild_id_here
|
||||||
+141
-141
@@ -1,142 +1,142 @@
|
|||||||
# Logs
|
# Logs
|
||||||
logs
|
logs
|
||||||
*.log
|
*.log
|
||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
yarn-debug.log*
|
yarn-debug.log*
|
||||||
yarn-error.log*
|
yarn-error.log*
|
||||||
lerna-debug.log*
|
lerna-debug.log*
|
||||||
|
|
||||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||||
|
|
||||||
# Runtime data
|
# Runtime data
|
||||||
pids
|
pids
|
||||||
*.pid
|
*.pid
|
||||||
*.seed
|
*.seed
|
||||||
*.pid.lock
|
*.pid.lock
|
||||||
|
|
||||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||||
lib-cov
|
lib-cov
|
||||||
|
|
||||||
# Coverage directory used by tools like istanbul
|
# Coverage directory used by tools like istanbul
|
||||||
coverage
|
coverage
|
||||||
*.lcov
|
*.lcov
|
||||||
|
|
||||||
# nyc test coverage
|
# nyc test coverage
|
||||||
.nyc_output
|
.nyc_output
|
||||||
|
|
||||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||||
.grunt
|
.grunt
|
||||||
|
|
||||||
# Bower dependency directory (https://bower.io/)
|
# Bower dependency directory (https://bower.io/)
|
||||||
bower_components
|
bower_components
|
||||||
|
|
||||||
# node-waf configuration
|
# node-waf configuration
|
||||||
.lock-wscript
|
.lock-wscript
|
||||||
|
|
||||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||||
build/Release
|
build/Release
|
||||||
|
|
||||||
# Dependency directories
|
# Dependency directories
|
||||||
node_modules/
|
node_modules/
|
||||||
jspm_packages/
|
jspm_packages/
|
||||||
|
|
||||||
# Snowpack dependency directory (https://snowpack.dev/)
|
# Snowpack dependency directory (https://snowpack.dev/)
|
||||||
web_modules/
|
web_modules/
|
||||||
|
|
||||||
# TypeScript cache
|
# TypeScript cache
|
||||||
*.tsbuildinfo
|
*.tsbuildinfo
|
||||||
|
|
||||||
# Optional npm cache directory
|
# Optional npm cache directory
|
||||||
.npm
|
.npm
|
||||||
|
|
||||||
# Optional eslint cache
|
# Optional eslint cache
|
||||||
.eslintcache
|
.eslintcache
|
||||||
|
|
||||||
# Optional stylelint cache
|
# Optional stylelint cache
|
||||||
.stylelintcache
|
.stylelintcache
|
||||||
|
|
||||||
# Optional REPL history
|
# Optional REPL history
|
||||||
.node_repl_history
|
.node_repl_history
|
||||||
|
|
||||||
# Output of 'npm pack'
|
# Output of 'npm pack'
|
||||||
*.tgz
|
*.tgz
|
||||||
|
|
||||||
# Yarn Integrity file
|
# Yarn Integrity file
|
||||||
.yarn-integrity
|
.yarn-integrity
|
||||||
|
|
||||||
# database
|
# database
|
||||||
db.json
|
db.json
|
||||||
|
|
||||||
# dotenv environment variable files
|
# dotenv environment variable files
|
||||||
.env
|
.env
|
||||||
.env.*
|
.env.*
|
||||||
!.env.example
|
!.env.example
|
||||||
|
|
||||||
# parcel-bundler cache (https://parceljs.org/)
|
# parcel-bundler cache (https://parceljs.org/)
|
||||||
.cache
|
.cache
|
||||||
.parcel-cache
|
.parcel-cache
|
||||||
|
|
||||||
# Next.js build output
|
# Next.js build output
|
||||||
.next
|
.next
|
||||||
out
|
out
|
||||||
|
|
||||||
# Nuxt.js build / generate output
|
# Nuxt.js build / generate output
|
||||||
.nuxt
|
.nuxt
|
||||||
dist
|
dist
|
||||||
|
|
||||||
# Gatsby files
|
# Gatsby files
|
||||||
.cache/
|
.cache/
|
||||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||||
# public
|
# public
|
||||||
|
|
||||||
# vuepress build output
|
# vuepress build output
|
||||||
.vuepress/dist
|
.vuepress/dist
|
||||||
|
|
||||||
# vuepress v2.x temp and cache directory
|
# vuepress v2.x temp and cache directory
|
||||||
.temp
|
.temp
|
||||||
.cache
|
.cache
|
||||||
|
|
||||||
# Sveltekit cache directory
|
# Sveltekit cache directory
|
||||||
.svelte-kit/
|
.svelte-kit/
|
||||||
|
|
||||||
# vitepress build output
|
# vitepress build output
|
||||||
**/.vitepress/dist
|
**/.vitepress/dist
|
||||||
|
|
||||||
# vitepress cache directory
|
# vitepress cache directory
|
||||||
**/.vitepress/cache
|
**/.vitepress/cache
|
||||||
|
|
||||||
# Docusaurus cache and generated files
|
# Docusaurus cache and generated files
|
||||||
.docusaurus
|
.docusaurus
|
||||||
|
|
||||||
# Serverless directories
|
# Serverless directories
|
||||||
.serverless/
|
.serverless/
|
||||||
|
|
||||||
# FuseBox cache
|
# FuseBox cache
|
||||||
.fusebox/
|
.fusebox/
|
||||||
|
|
||||||
# DynamoDB Local files
|
# DynamoDB Local files
|
||||||
.dynamodb/
|
.dynamodb/
|
||||||
|
|
||||||
# Firebase cache directory
|
# Firebase cache directory
|
||||||
.firebase/
|
.firebase/
|
||||||
|
|
||||||
# TernJS port file
|
# TernJS port file
|
||||||
.tern-port
|
.tern-port
|
||||||
|
|
||||||
# Stores VSCode versions used for testing VSCode extensions
|
# Stores VSCode versions used for testing VSCode extensions
|
||||||
.vscode-test
|
.vscode-test
|
||||||
|
|
||||||
# yarn v3
|
# yarn v3
|
||||||
.pnp.*
|
.pnp.*
|
||||||
.yarn/*
|
.yarn/*
|
||||||
!.yarn/patches
|
!.yarn/patches
|
||||||
!.yarn/plugins
|
!.yarn/plugins
|
||||||
!.yarn/releases
|
!.yarn/releases
|
||||||
!.yarn/sdks
|
!.yarn/sdks
|
||||||
!.yarn/versions
|
!.yarn/versions
|
||||||
|
|
||||||
# Vite logs files
|
# Vite logs files
|
||||||
vite.config.js.timestamp-*
|
vite.config.js.timestamp-*
|
||||||
vite.config.ts.timestamp-*
|
vite.config.ts.timestamp-*
|
||||||
@@ -1,121 +1,121 @@
|
|||||||
# twitter (v3)
|
# twitter (v3)
|
||||||
|
|
||||||
a discord.js v14 moderation (+ more) bot
|
a discord.js v14 moderation (+ more) bot
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## features
|
## features
|
||||||
|
|
||||||
- prefix command system — commands triggered by a configurable prefix (default `!`)
|
- prefix command system — commands triggered by a configurable prefix (default `!`)
|
||||||
- auto-loading — commands and events are loaded automatically from their folders
|
- auto-loading — commands and events are loaded automatically from their folders
|
||||||
- aliases — each command can define one or more aliases
|
- aliases — each command can define one or more aliases
|
||||||
- winston logging — coloured console output + rolling log files (`logs/combined.log`, `logs/error.log`)
|
- winston logging — coloured console output + rolling log files (`logs/combined.log`, `logs/error.log`)
|
||||||
- global error handling — unhandled rejections and uncaught exceptions are caught and logged
|
- global error handling — unhandled rejections and uncaught exceptions are caught and logged
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## project structure
|
## project structure
|
||||||
|
|
||||||
```
|
```
|
||||||
src/
|
src/
|
||||||
├── index.js # entry point — creates the client, loads handlers
|
├── index.js # entry point — creates the client, loads handlers
|
||||||
├── commands/
|
├── commands/
|
||||||
│ ├── help.js # !help — lists commands or shows command detail
|
│ ├── help.js # !help — lists commands or shows command detail
|
||||||
│ └── ping.js # !ping — latency check
|
│ └── ping.js # !ping — latency check
|
||||||
├── events/
|
├── events/
|
||||||
│ ├── ready.js # fires once when the bot is online
|
│ ├── ready.js # fires once when the bot is online
|
||||||
│ └── messageCreate.js # parses every message for prefix commands
|
│ └── messageCreate.js # parses every message for prefix commands
|
||||||
├── handlers/
|
├── handlers/
|
||||||
│ ├── commandHandler.js # reads src/commands/ and registers commands
|
│ ├── commandHandler.js # reads src/commands/ and registers commands
|
||||||
│ └── eventHandler.js # reads src/events/ and registers discord events
|
│ └── eventHandler.js # reads src/events/ and registers discord events
|
||||||
└── utils/
|
└── utils/
|
||||||
└── logger.js # winston logger instance
|
└── logger.js # winston logger instance
|
||||||
logs/ # created automatically at runtime (git-ignored)
|
logs/ # created automatically at runtime (git-ignored)
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## setup
|
## setup
|
||||||
|
|
||||||
### 1. clone & install dependencies
|
### 1. clone & install dependencies
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/yhqe/twitter_v3.git
|
git clone https://github.com/yhqe/twitter_v3.git
|
||||||
cd twitter_v3
|
cd twitter_v3
|
||||||
npm install
|
npm install
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. configure environment variables
|
### 2. configure environment variables
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cp .env.example .env
|
cp .env.example .env
|
||||||
```
|
```
|
||||||
|
|
||||||
open `.env` and fill in:
|
open `.env` and fill in:
|
||||||
|
|
||||||
| variable | required | description |
|
| variable | required | description |
|
||||||
|-------------|----------|------------------------------------------------------|
|
|-------------|----------|------------------------------------------------------|
|
||||||
| `BOT_TOKEN` | yes | your bot token from the discord developer portal |
|
| `BOT_TOKEN` | yes | your bot token from the discord developer portal |
|
||||||
| `PREFIX` | no | command prefix (default: `!`) |
|
| `PREFIX` | no | command prefix (default: `!`) |
|
||||||
| `GUILD_ID` | no | test server id (handy for dev stuff) |
|
| `GUILD_ID` | no | test server id (handy for dev stuff) |
|
||||||
|
|
||||||
### 3. enable the message content intent
|
### 3. enable the message content intent
|
||||||
|
|
||||||
go to your application in the [discord developer portal](https://discord.com/developers/applications), open **bot → privileged gateway intents**, and enable **message content intent**. you need this for prefix commands.
|
go to your application in the [discord developer portal](https://discord.com/developers/applications), open **bot → privileged gateway intents**, and enable **message content intent**. you need this for prefix commands.
|
||||||
|
|
||||||
### 4. start the bot
|
### 4. start the bot
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# production
|
# production
|
||||||
npm start
|
npm start
|
||||||
|
|
||||||
# development (auto-restarts on file changes, node.js 18+)
|
# development (auto-restarts on file changes, node.js 18+)
|
||||||
npm run dev
|
npm run dev
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## adding commands
|
## adding commands
|
||||||
|
|
||||||
create a file in `src/commands/`. the handler will load it automatically on next start.
|
create a file in `src/commands/`. the handler will load it automatically on next start.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
name: 'example', // primary command name (also used as the key)
|
name: 'example', // primary command name (also used as the key)
|
||||||
description: 'An example command.',
|
description: 'An example command.',
|
||||||
aliases: ['ex'], // optional aliases
|
aliases: ['ex'], // optional aliases
|
||||||
usage: 'example <text>', // shown in !help example
|
usage: 'example <text>', // shown in !help example
|
||||||
|
|
||||||
async execute(client, message, args) {
|
async execute(client, message, args) {
|
||||||
await message.reply(`You said: ${args.join(' ')}`);
|
await message.reply(`You said: ${args.join(' ')}`);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
## adding events
|
## adding events
|
||||||
|
|
||||||
create a file in `src/events/`. set `once: true` if it should fire only once (e.g. `ready`).
|
create a file in `src/events/`. set `once: true` if it should fire only once (e.g. `ready`).
|
||||||
|
|
||||||
```js
|
```js
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const { Events } = require('discord.js');
|
const { Events } = require('discord.js');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
name: Events.GuildMemberAdd,
|
name: Events.GuildMemberAdd,
|
||||||
|
|
||||||
async execute(client, member) {
|
async execute(client, member) {
|
||||||
console.log(`${member.user.tag} joined ${member.guild.name}`);
|
console.log(`${member.user.tag} joined ${member.guild.name}`);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## logging
|
## logging
|
||||||
|
|
||||||
log files are written to the `logs/` directory (git-ignored). the log level defaults to `info` and can be overridden with the `LOG_LEVEL` environment variable (e.g. `LOG_LEVEL=debug npm start`).
|
log files are written to the `logs/` directory (git-ignored). the log level defaults to `info` and can be overridden with the `LOG_LEVEL` environment variable (e.g. `LOG_LEVEL=debug npm start`).
|
||||||
|
|
||||||
|
|
||||||
@@ -1,5 +1,8 @@
|
|||||||
{
|
{
|
||||||
"autoroles": {
|
"autoroles": {
|
||||||
"1133441692196950101": "1192595134026616894"
|
"1133441692196950101": "1192595134026616894"
|
||||||
|
},
|
||||||
|
"autobans": {
|
||||||
|
"1133441692196950101": "1264634623950848158"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+2467
-2454
File diff suppressed because it is too large.
Load diff
Generated
+609
-609
File diff suppressed because it is too large.
Load diff
+139
-139
@@ -1,139 +1,139 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const { time } = require("discord.js");
|
const { time } = require("discord.js");
|
||||||
const logger = require('../../utils/logger');
|
const logger = require('../../utils/logger');
|
||||||
|
|
||||||
async function getAvailableCapes(username) {
|
async function getAvailableCapes(username) {
|
||||||
const capes =[];
|
const capes =[];
|
||||||
|
|
||||||
const mojangReq = await Promise.allSettled([
|
const mojangReq = await Promise.allSettled([
|
||||||
fetch(`https://api.ashcon.app/mojang/v2/user/${username}`),
|
fetch(`https://api.ashcon.app/mojang/v2/user/${username}`),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (mojangReq.status === 'fulfilled' && mojangReq.value.ok) {
|
if (mojangReq.status === 'fulfilled' && mojangReq.value.ok) {
|
||||||
const mojangData = await mojangReq.value.json();
|
const mojangData = await mojangReq.value.json();
|
||||||
if (mojangData.textures && mojangData.textures.cape) {
|
if (mojangData.textures && mojangData.textures.cape) {
|
||||||
capes.push({
|
capes.push({
|
||||||
source: 'Official (Equipped)',
|
source: 'Official (Equipped)',
|
||||||
url: mojangData.textures.cape.url
|
url: mojangData.textures.cape.url
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return capes;
|
return capes;
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
name: 'mc',
|
name: 'mc',
|
||||||
description: `request different information about a minecraft user`,
|
description: `request different information about a minecraft user`,
|
||||||
aliases: ['minecraft'],
|
aliases: ['minecraft'],
|
||||||
usage: 'mc <username>',
|
usage: 'mc <username>',
|
||||||
|
|
||||||
async execute(client, message, args) {
|
async execute(client, message, args) {
|
||||||
var embed;
|
var embed;
|
||||||
|
|
||||||
let sent = await message.reply({
|
let sent = await message.reply({
|
||||||
content: null, embeds: [{
|
content: null, embeds: [{
|
||||||
color: 0x8aa2b3,
|
color: 0x8aa2b3,
|
||||||
title: '',
|
title: '',
|
||||||
author: {
|
author: {
|
||||||
name: message.author.username,
|
name: message.author.username,
|
||||||
icon_url: message.author.displayAvatarURL(),
|
icon_url: message.author.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
description: '<a:loading_icon:1366587619890302998> fetching...',
|
description: '<a:loading_icon:1366587619890302998> fetching...',
|
||||||
footer: {
|
footer: {
|
||||||
text: `twitter @ ${message.guild.name}`,
|
text: `twitter @ ${message.guild.name}`,
|
||||||
icon_url: client.user.displayAvatarURL(),
|
icon_url: client.user.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
timestamp: new Date(),
|
timestamp: new Date(),
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
|
|
||||||
const username = args[0];
|
const username = args[0];
|
||||||
if (!username) {
|
if (!username) {
|
||||||
embed = {
|
embed = {
|
||||||
color: 0x8aa2b3,
|
color: 0x8aa2b3,
|
||||||
title: '',
|
title: '',
|
||||||
description: '<:no:1481811955592466492> please provide a valid minecraft username!',
|
description: '<:no:1481811955592466492> please provide a valid minecraft username!',
|
||||||
footer: {
|
footer: {
|
||||||
text: `twitter @ ${message.guild.name}`,
|
text: `twitter @ ${message.guild.name}`,
|
||||||
icon_url: client.user.displayAvatarURL(),
|
icon_url: client.user.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
timestamp: new Date(),
|
timestamp: new Date(),
|
||||||
};
|
};
|
||||||
return await sent.edit({ content: null, embeds: [embed] });
|
return await sent.edit({ content: null, embeds: [embed] });
|
||||||
}
|
}
|
||||||
|
|
||||||
const uuid_res = await fetch(`https://api.mojang.com/users/profiles/minecraft/${username}`);
|
const uuid_res = await fetch(`https://api.mojang.com/users/profiles/minecraft/${username}`);
|
||||||
|
|
||||||
const uuid = await uuid_res.json().then(res => res.id).catch(err => {
|
const uuid = await uuid_res.json().then(res => res.id).catch(err => {
|
||||||
embed = {
|
embed = {
|
||||||
color: 0x8aa2b3,
|
color: 0x8aa2b3,
|
||||||
title: '',
|
title: '',
|
||||||
description: '<:no:1481811955592466492> cannot fetch uuid!',
|
description: '<:no:1481811955592466492> cannot fetch uuid!',
|
||||||
footer: {
|
footer: {
|
||||||
text: `twitter @ ${message.guild.name}`,
|
text: `twitter @ ${message.guild.name}`,
|
||||||
icon_url: client.user.displayAvatarURL(),
|
icon_url: client.user.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
timestamp: new Date(),
|
timestamp: new Date(),
|
||||||
};
|
};
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
|
||||||
const res = await fetch(`https://sessionserver.mojang.com/session/minecraft/profile/${uuid}`);
|
const res = await fetch(`https://sessionserver.mojang.com/session/minecraft/profile/${uuid}`);
|
||||||
const data = await res.json().then(res => res).catch(err => {
|
const data = await res.json().then(res => res).catch(err => {
|
||||||
embed = {
|
embed = {
|
||||||
color: 0x8aa2b3,
|
color: 0x8aa2b3,
|
||||||
title: '',
|
title: '',
|
||||||
description: '<:no:1481811955592466492> cannot fetch data!',
|
description: '<:no:1481811955592466492> cannot fetch data!',
|
||||||
footer: {
|
footer: {
|
||||||
text: `twitter @ ${message.guild.name}`,
|
text: `twitter @ ${message.guild.name}`,
|
||||||
icon_url: client.user.displayAvatarURL(),
|
icon_url: client.user.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
timestamp: new Date(),
|
timestamp: new Date(),
|
||||||
};
|
};
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
|
||||||
getAvailableCapes(`${data.name}`).then(capes => {
|
getAvailableCapes(`${data.name}`).then(capes => {
|
||||||
logger.debug(`found ${capes.length} cape(s):`);
|
logger.debug(`found ${capes.length} cape(s):`);
|
||||||
logger.debug(capes);
|
logger.debug(capes);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!data) return await sent.edit({ content: null, embeds: [embed] });
|
if (!data) return await sent.edit({ content: null, embeds: [embed] });
|
||||||
|
|
||||||
const skin = await fetch (`https://minotar.net/helm/${data.name}/420.png`).then(res => res.url).catch(err => null);
|
const skin = await fetch (`https://minotar.net/helm/${data.name}/420.png`).then(res => res.url).catch(err => null);
|
||||||
|
|
||||||
const capes = data.properties[0].value;
|
const capes = data.properties[0].value;
|
||||||
const decoded_capes = Buffer.from(capes, 'base64').toString('utf-8');
|
const decoded_capes = Buffer.from(capes, 'base64').toString('utf-8');
|
||||||
const cape_url = JSON.parse(decoded_capes).textures.CAPE ? JSON.parse(decoded_capes).textures.CAPE.url : null;
|
const cape_url = JSON.parse(decoded_capes).textures.CAPE ? JSON.parse(decoded_capes).textures.CAPE.url : null;
|
||||||
|
|
||||||
logger.debug(`[mc] fetched data for "${username}": ${JSON.stringify(data)}`);
|
logger.debug(`[mc] fetched data for "${username}": ${JSON.stringify(data)}`);
|
||||||
logger.debug(`[mc] fetched cape data for "${username}": ${JSON.stringify(cape_url)}`);
|
logger.debug(`[mc] fetched cape data for "${username}": ${JSON.stringify(cape_url)}`);
|
||||||
|
|
||||||
embed = {
|
embed = {
|
||||||
color: 0x8aa2b3,
|
color: 0x8aa2b3,
|
||||||
title: '',
|
title: '',
|
||||||
author: {
|
author: {
|
||||||
name: message.author.username,
|
name: message.author.username,
|
||||||
icon_url: message.author.displayAvatarURL(),
|
icon_url: message.author.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
description: `**[${data.name}](https://namemc.com/profile/${data.name})**`,
|
description: `**[${data.name}](https://namemc.com/profile/${data.name})**`,
|
||||||
fields: [
|
fields: [
|
||||||
{ name: 'uuid', value: `${data.id}`, inline: true },
|
{ name: 'uuid', value: `${data.id}`, inline: true },
|
||||||
],
|
],
|
||||||
footer: {
|
footer: {
|
||||||
text: `twitter @ ${message.guild.name}`,
|
text: `twitter @ ${message.guild.name}`,
|
||||||
icon_url: client.user.displayAvatarURL(),
|
icon_url: client.user.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
timestamp: new Date(),
|
timestamp: new Date(),
|
||||||
thumbnail: {
|
thumbnail: {
|
||||||
url: skin,
|
url: skin,
|
||||||
height: 1024,
|
height: 1024,
|
||||||
width: 1024,
|
width: 1024,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
await sent.edit({ content: null, embeds: [embed] });
|
await sent.edit({ content: null, embeds: [embed] });
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
+423
-386
@@ -1,386 +1,423 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const { time } = require("discord.js");
|
const { time } = require("discord.js");
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const logger = require('../../utils/logger');
|
const logger = require('../../utils/logger');
|
||||||
|
|
||||||
async function fetch_avatar(id) {
|
async function fetch_avatar(id) {
|
||||||
const res = await fetch(`https://thumbnails.roproxy.com/v1/users/avatar?userIds=${id}&size=420x420&format=Png&isCircular=false`, {
|
const res = await fetch(`https://thumbnails.roproxy.com/v1/users/avatar?userIds=${id}&size=420x420&format=Png&isCircular=false`, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: { 'Content-Type': 'application/json' }
|
headers: { 'Content-Type': 'application/json' }
|
||||||
});
|
});
|
||||||
|
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
logger.debug(`[fetch_avatar] ${JSON.stringify(data)}`);
|
logger.debug(`[fetch_avatar] ${JSON.stringify(data)}`);
|
||||||
if (data.data && data.data[0] && data.data[0].imageUrl) {
|
if (data.data && data.data[0] && data.data[0].imageUrl) {
|
||||||
logger.debug(`[fetch_avatar] fetched avatar for user id ${id}: ${data.data[0].imageUrl}`);
|
logger.debug(`[fetch_avatar] fetched avatar for user id ${id}: ${data.data[0].imageUrl}`);
|
||||||
return data.data[0].imageUrl;
|
return data.data[0].imageUrl;
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetch_item_thumb(id) {
|
async function fetch_item_thumb(id) {
|
||||||
const res = await fetch(`https://thumbnails.roproxy.com/v1/assets?assetIds=${id}&returnPolicy=PlaceHolder&size=420x420&format=Png&isCircular=false`, {
|
const res = await fetch(`https://thumbnails.roproxy.com/v1/assets?assetIds=${id}&returnPolicy=PlaceHolder&size=420x420&format=Png&isCircular=false`, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: { 'Content-Type': 'application/json' }
|
headers: { 'Content-Type': 'application/json' }
|
||||||
});
|
});
|
||||||
|
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
logger.debug(`[fetch_item_thumb] ${JSON.stringify(data)}`);
|
logger.debug(`[fetch_item_thumb] ${JSON.stringify(data)}`);
|
||||||
if (data.data && data.data[0] && data.data[0].imageUrl) {
|
if (data.data && data.data[0] && data.data[0].imageUrl) {
|
||||||
logger.debug(`[fetch_item_thumb] fetched item thumbnail for item id ${id}: ${data.data[0].imageUrl}`);
|
logger.debug(`[fetch_item_thumb] fetched item thumbnail for item id ${id}: ${data.data[0].imageUrl}`);
|
||||||
return data.data[0].imageUrl;
|
return data.data[0].imageUrl;
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function to_unix_timestamp(dateString) {
|
function to_unix_timestamp(dateString) {
|
||||||
const unixSeconds = Math.floor(new Date(dateString).getTime() / 1000);
|
const unixSeconds = Math.floor(new Date(dateString).getTime() / 1000);
|
||||||
logger.debug(unixSeconds);
|
logger.debug(unixSeconds);
|
||||||
return unixSeconds;
|
return unixSeconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
name: 'rbx',
|
name: 'rbx',
|
||||||
description: `various commands related to roblox`,
|
description: `various commands related to roblox`,
|
||||||
aliases: ['roblox'],
|
aliases: ['roblox'],
|
||||||
usage: 'rbx user <username>\n.rbx item <item id>\n.rbx group <group id>\n.rbx game <game id>',
|
usage: 'rbx user <username>\n.rbx item <item id>\n.rbx group <group id>\n.rbx game <game id>\n.rbx avatar <username>',
|
||||||
|
|
||||||
async execute(client, message) {
|
async execute(client, message) {
|
||||||
var embed = {};
|
var embed = {};
|
||||||
const args = message.content.split(' ').slice(1);
|
const args = message.content.split(' ').slice(1);
|
||||||
|
|
||||||
if (args.length < 2) {
|
if (args.length < 2) {
|
||||||
return message.reply({
|
return message.reply({
|
||||||
content: null, embeds: [{
|
content: null, embeds: [{
|
||||||
color: 0x8aa2b3,
|
color: 0x8aa2b3,
|
||||||
author: {
|
author: {
|
||||||
name: message.author.username,
|
name: message.author.username,
|
||||||
icon_url: message.author.displayAvatarURL(),
|
icon_url: message.author.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
description: '<:no:1481811955592466492> please provide a subcommand and an argument!',
|
description: '<:no:1481811955592466492> please provide a subcommand and an argument!',
|
||||||
footer: {
|
footer: {
|
||||||
text: `twitter @ ${message.guild.name}`,
|
text: `twitter @ ${message.guild.name}`,
|
||||||
icon_url: client.user.displayAvatarURL(),
|
icon_url: client.user.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
timestamp: new Date(),
|
timestamp: new Date(),
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const subcommand = args[0].toLowerCase();
|
const subcommand = args[0].toLowerCase();
|
||||||
const argument = args.slice(1).join(' ');
|
const argument = args.slice(1).join(' ');
|
||||||
|
|
||||||
let sent = await message.reply({
|
let sent = await message.reply({
|
||||||
content: null, embeds: [{
|
content: null, embeds: [{
|
||||||
color: 0x8aa2b3,
|
color: 0x8aa2b3,
|
||||||
title: '',
|
title: '',
|
||||||
author: {
|
author: {
|
||||||
name: message.author.username,
|
name: message.author.username,
|
||||||
icon_url: message.author.displayAvatarURL(),
|
icon_url: message.author.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
description: '<a:loading_icon:1366587619890302998> fetching...',
|
description: '<a:loading_icon:1366587619890302998> fetching...',
|
||||||
footer: {
|
footer: {
|
||||||
text: `twitter @ ${message.guild.name}`,
|
text: `twitter @ ${message.guild.name}`,
|
||||||
icon_url: client.user.displayAvatarURL(),
|
icon_url: client.user.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
timestamp: new Date(),
|
timestamp: new Date(),
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
|
|
||||||
let latency = Date.now() - message.createdTimestamp;
|
let latency = Date.now() - message.createdTimestamp;
|
||||||
let apiLatency = Math.round(client.ws.ping);
|
let apiLatency = Math.round(client.ws.ping);
|
||||||
|
|
||||||
if (subcommand === 'user' || subcommand === 'u') {
|
if (subcommand === 'user' || subcommand === 'u') {
|
||||||
try {
|
try {
|
||||||
const res = await fetch(`https://users.roproxy.com/v1/usernames/users`, {
|
const res = await fetch(`https://users.roproxy.com/v1/usernames/users`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${process.env.ROBLOSECURITY}` },
|
headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${process.env.ROBLOSECURITY}` },
|
||||||
body: JSON.stringify({ usernames: [argument], excludeBannedUsers: false })
|
body: JSON.stringify({ usernames: [argument], excludeBannedUsers: false })
|
||||||
});
|
});
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
logger.debug(`[rbx] fetched user data (roblox, standard) for "${argument}": ${JSON.stringify(data)}`);
|
logger.debug(`[rbx] fetched user data (roblox, standard) for "${argument}": ${JSON.stringify(data)}`);
|
||||||
|
|
||||||
if (!data.data || !data.data[0]) {
|
if (!data.data || !data.data[0]) {
|
||||||
throw new Error('User not found');
|
throw new Error('User not found');
|
||||||
}
|
}
|
||||||
const extra_res = await fetch(`https://users.roproxy.com/v1/users/${data.data[0].id}`, {
|
const extra_res = await fetch(`https://users.roproxy.com/v1/users/${data.data[0].id}`, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${process.env.ROBLOSECURITY}` }
|
headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${process.env.ROBLOSECURITY}` }
|
||||||
});
|
});
|
||||||
const extra_data = await extra_res.json();
|
const extra_data = await extra_res.json();
|
||||||
logger.debug(`[rbx] fetched user data (roblox, extra) for "${argument}": ${JSON.stringify(extra_data)}`);
|
logger.debug(`[rbx] fetched user data (roblox, extra) for "${argument}": ${JSON.stringify(extra_data)}`);
|
||||||
|
|
||||||
const r_res = await fetch(`https://api.rolimons.com/players/v1/playerinfo/${data.data[0].id}`, {
|
const r_res = await fetch(`https://api.rolimons.com/players/v1/playerinfo/${data.data[0].id}`, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: { 'Content-Type': 'application/json' }
|
headers: { 'Content-Type': 'application/json' }
|
||||||
});
|
});
|
||||||
let r_data = {};
|
let r_data = {};
|
||||||
if (r_res.ok) {
|
if (r_res.ok) {
|
||||||
r_data = await r_res.json();
|
r_data = await r_res.json();
|
||||||
} else {
|
} else {
|
||||||
logger.warn(`[rbx] Failed to fetch rolimons playerinfo for id ${data.data[0].id}: HTTP ${r_res.status}`);
|
logger.warn(`[rbx] Failed to fetch rolimons playerinfo for id ${data.data[0].id}: HTTP ${r_res.status}`);
|
||||||
r_data = {};
|
r_data = {};
|
||||||
}
|
}
|
||||||
logger.debug(`[rbx] fetched user data (rolimons) for "${argument}": ${JSON.stringify(r_data)}`);
|
logger.debug(`[rbx] fetched user data (rolimons) for "${argument}": ${JSON.stringify(r_data)}`);
|
||||||
|
|
||||||
const ra_res = await fetch(`https://api.rolimons.com/players/v1/playerassets/${data.data[0].id}`, {
|
const ra_res = await fetch(`https://api.rolimons.com/players/v1/playerassets/${data.data[0].id}`, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: { 'Content-Type': 'application/json' }
|
headers: { 'Content-Type': 'application/json' }
|
||||||
});
|
});
|
||||||
const ra_data = await ra_res.json();
|
const ra_data = await ra_res.json();
|
||||||
logger.debug(`[rbx] fetched user data (rolimons, assets) for "${argument}": ${JSON.stringify(ra_data)}`);
|
logger.debug(`[rbx] fetched user data (rolimons, assets) for "${argument}": ${JSON.stringify(ra_data)}`);
|
||||||
|
|
||||||
if (!data.data || !data.data[0]) {
|
if (!data.data || !data.data[0]) {
|
||||||
embed = {
|
embed = {
|
||||||
color: 0x8aa2b3,
|
color: 0x8aa2b3,
|
||||||
author: {
|
author: {
|
||||||
name: message.author.username,
|
name: message.author.username,
|
||||||
icon_url: message.author.displayAvatarURL(),
|
icon_url: message.author.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
description: '<:no:1481811955592466492> could not find a roblox user with that username!',
|
description: '<:no:1481811955592466492> could not find a roblox user with that username!',
|
||||||
footer: {
|
footer: {
|
||||||
text: `twitter @ ${message.guild.name}`,
|
text: `twitter @ ${message.guild.name}`,
|
||||||
icon_url: client.user.displayAvatarURL(),
|
icon_url: client.user.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
timestamp: new Date(),
|
timestamp: new Date(),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const user = data.data[0];
|
const user = data.data[0];
|
||||||
const avatarUrl = await fetch_avatar(user.id);
|
const avatarUrl = await fetch_avatar(user.id);
|
||||||
|
|
||||||
const hasCheckmark = user.hasVerifiedBadge;
|
const hasCheckmark = user.hasVerifiedBadge;
|
||||||
const hasPremium = r_data.premium;
|
const hasPremium = r_data.premium;
|
||||||
const isOnline = ra_data.isOnline;
|
const isOnline = ra_data.isOnline;
|
||||||
|
|
||||||
const viewInvRes = await fetch(`https://inventory.roproxy.com/v1/users/${user.id}/can-view-inventory`);
|
const viewInvRes = await fetch(`https://inventory.roproxy.com/v1/users/${user.id}/can-view-inventory`);
|
||||||
const isInvPublic = (await viewInvRes.json()).canView;
|
const isInvPublic = (await viewInvRes.json()).canView;
|
||||||
|
|
||||||
const formatted_desc = (extra_data.description || "no description")
|
const formatted_desc = (extra_data.description || "no description")
|
||||||
.split('\n')
|
.split('\n')
|
||||||
.map(line => line.trim() ? `-# *${line}*` : '')
|
.map(line => line.trim() ? `-# *${line}*` : '')
|
||||||
.join('\n');
|
.join('\n');
|
||||||
|
|
||||||
embed = {
|
embed = {
|
||||||
color: 0x8aa2b3,
|
color: 0x8aa2b3,
|
||||||
author: {
|
author: {
|
||||||
name: message.author.username,
|
name: message.author.username,
|
||||||
icon_url: message.author.displayAvatarURL(),
|
icon_url: message.author.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
description: `**[${user.displayName}](https://www.roblox.com/users/${user.id}/profile)** [(${user.name})](https://www.rolimons.com/player/${user.id}) ${isOnline ? "<:online:1482657396362055826>" : "<:offline:1482657564650115073>"} ${hasPremium ? "<:premium:1482660040358760602>" : ""} ${hasCheckmark ? "<:Verified:1376786225486364823>" : ""}\n${formatted_desc}`,
|
description: `**[${user.displayName}](https://www.roblox.com/users/${user.id}/profile)** [(${user.name})](https://www.rolimons.com/player/${user.id}) ${isOnline ? "<:online:1482657396362055826>" : "<:offline:1482657564650115073>"} ${hasPremium ? "<:premium:1482660040358760602>" : ""} ${hasCheckmark ? "<:Verified:1376786225486364823>" : ""}\n${formatted_desc}`,
|
||||||
fields: [
|
fields: [
|
||||||
{ name: 'id', value: String(extra_data.id), inline: true },
|
{ name: 'id', value: String(extra_data.id), inline: true },
|
||||||
{ name: 'rap', value: String(r_data.rap), inline: true },
|
{ name: 'rap', value: String(r_data.rap), inline: true },
|
||||||
{ name: 'value', value: String(r_data.value), inline: true },
|
{ name: 'value', value: String(r_data.value), inline: true },
|
||||||
{ name: 'inventory', value: `${isInvPublic ? 'public' : 'private'}`, inline: true },
|
{ name: 'inventory', value: `${isInvPublic ? 'public' : 'private'}`, inline: true },
|
||||||
{ name: 'terminated', value: String(r_data.terminated), inline: true },
|
{ name: 'terminated', value: String(r_data.terminated), inline: true },
|
||||||
{ name: 'date created', value: `<t:${to_unix_timestamp(String(extra_data.created))}:f>`, inline: true },
|
{ name: 'date created', value: `<t:${to_unix_timestamp(String(extra_data.created))}:f>`, inline: true },
|
||||||
{ name: 'last online', value: `${isOnline ? "now" : "<t:" + r_data.last_online + ":f>"}`, inline: true },
|
{ name: 'last online', value: `${isOnline ? "now" : "<t:" + r_data.last_online + ":f>"}`, inline: true },
|
||||||
],
|
],
|
||||||
thumbnail: {
|
thumbnail: {
|
||||||
url: avatarUrl,
|
url: avatarUrl,
|
||||||
height: 420,
|
height: 420,
|
||||||
width: 420,
|
width: 420,
|
||||||
},
|
},
|
||||||
footer: {
|
footer: {
|
||||||
text: `twitter @ ${message.guild.name}`,
|
text: `twitter @ ${message.guild.name}`,
|
||||||
icon_url: client.user.displayAvatarURL(),
|
icon_url: client.user.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
timestamp: new Date(),
|
timestamp: new Date(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error(`[rbx] failed to fetch user data for "${argument}":`, err);
|
logger.error(`[rbx] failed to fetch user data for "${argument}":`, err);
|
||||||
embed = {
|
embed = {
|
||||||
color: 0x8aa2b3,
|
color: 0x8aa2b3,
|
||||||
author: {
|
author: {
|
||||||
name: message.author.username,
|
name: message.author.username,
|
||||||
icon_url: message.author.displayAvatarURL(),
|
icon_url: message.author.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
description: `<:no:1481811955592466492> could not fetch data for user "${argument}"!`,
|
description: `<:no:1481811955592466492> could not fetch data for user "${argument}"!`,
|
||||||
footer: {
|
footer: {
|
||||||
text: `twitter @ ${message.guild.name}`,
|
text: `twitter @ ${message.guild.name}`,
|
||||||
icon_url: client.user.displayAvatarURL(),
|
icon_url: client.user.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
timestamp: new Date(),
|
timestamp: new Date(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (subcommand === 'item') {
|
} else if (subcommand === 'avatar') {
|
||||||
try {
|
try {
|
||||||
const res = await fetch(`https://economy.roproxy.com/v2/assets/${argument}/details`, {
|
const res = await fetch(`https://thumbnails.roproxy.com/v1/users/avatar?userIds=${id}&size=420x420&format=Png&isCircular=false`, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: {
|
headers: { 'Content-Type': 'application/json' }
|
||||||
'Content-Type': 'application/json',
|
});
|
||||||
'Cookie': `.ROBLOSECURITY=${process.env.ROBLOSECURITY}`
|
|
||||||
}
|
const data = await res.json();
|
||||||
});
|
embed = {
|
||||||
const p_res = await fetch(`https://thumbnails.roproxy.com/v1/assets?assetIds=${argument}&returnPolicy=PlaceHolder&size=420x420&format=Png&isCircular=false`, {
|
color: 0x8aa2b3,
|
||||||
method: 'GET',
|
author: {
|
||||||
headers: {
|
name: message.author.username,
|
||||||
'Content-Type': 'application/json',
|
icon_url: message.author.displayAvatarURL(),
|
||||||
'Cookie': `.ROBLOSECURITY=${process.env.ROBLOSECURITY}`
|
},
|
||||||
}
|
description: `${}`,
|
||||||
});
|
footer: {
|
||||||
const resale_res = await fetch(`https://economy.roproxy.com/v1/assets/${argument}/resale-data`, {
|
text: `twitter @ ${message.guild.name}`,
|
||||||
method: 'GET',
|
icon_url: client.user.displayAvatarURL(),
|
||||||
headers: {
|
},
|
||||||
'Content-Type': 'application/json',
|
timestamp: new Date(),
|
||||||
'Cookie': `.ROBLOSECURITY=${process.env.ROBLOSECURITY}`
|
};
|
||||||
}
|
} catch (err) {
|
||||||
});
|
logger.error(`[rbx] failed to fetch avatar for user id "${argument}":`, err);
|
||||||
|
embed = {
|
||||||
const item = await res.json();
|
color: 0x8aa2b3,
|
||||||
logger.debug(`[rbx] fetched item data (roblox) for "${argument}": ${JSON.stringify(item)}`);
|
author: {
|
||||||
|
name: message.author.username,
|
||||||
const resale_data = await resale_res.json();
|
icon_url: message.author.displayAvatarURL(),
|
||||||
logger.debug(`[rbx] fetched resale data for "${argument}": ${JSON.stringify(resale_data)}`);
|
},
|
||||||
|
description: `<:no:1481811955592466492> could not fetch avatar data for user "${argument}"!`,
|
||||||
let itemsJson;
|
footer: {
|
||||||
try {
|
text: `twitter @ ${message.guild.name}`,
|
||||||
const itemsPath = path.resolve(process.cwd(), 'items.json');
|
icon_url: client.user.displayAvatarURL(),
|
||||||
const itemsRaw = fs.readFileSync(itemsPath, 'utf8');
|
},
|
||||||
itemsJson = JSON.parse(itemsRaw);
|
timestamp: new Date(),
|
||||||
if (itemsJson.items && itemsJson.items[argument]) {
|
};
|
||||||
logger.debug(`[rbx] found item ${argument} in items.json: ${JSON.stringify(itemsJson.items[argument])}`);
|
}
|
||||||
}
|
} else if (subcommand === 'item') {
|
||||||
} catch (e) {
|
try {
|
||||||
logger.warn(`[rbx] could not read items.json: ${e.message}`);
|
const res = await fetch(`https://economy.roproxy.com/v2/assets/${argument}/details`, {
|
||||||
}
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
let item_e = itemsJson.items[argument];
|
'Content-Type': 'application/json',
|
||||||
|
'Cookie': `.ROBLOSECURITY=${process.env.ROBLOSECURITY}`
|
||||||
var hasAcronym = false;
|
}
|
||||||
if (item_e[1] = "") {
|
});
|
||||||
hasAcronym = false;
|
const p_res = await fetch(`https://thumbnails.roproxy.com/v1/assets?assetIds=${argument}&returnPolicy=PlaceHolder&size=420x420&format=Png&isCircular=false`, {
|
||||||
} else {
|
method: 'GET',
|
||||||
hasAcronym = true;
|
headers: {
|
||||||
}
|
'Content-Type': 'application/json',
|
||||||
|
'Cookie': `.ROBLOSECURITY=${process.env.ROBLOSECURITY}`
|
||||||
const item_thumb = await fetch_item_thumb(item.AssetId);
|
}
|
||||||
const is_offsale = item.IsForSale;
|
});
|
||||||
|
const resale_res = await fetch(`https://economy.roproxy.com/v1/assets/${argument}/resale-data`, {
|
||||||
const is_limited = item.IsLimited;
|
method: 'GET',
|
||||||
const is_limited_unique = item.IsLimitedUnique;
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
const is_limited_at_all = is_limited || is_limited_unique;
|
'Cookie': `.ROBLOSECURITY=${process.env.ROBLOSECURITY}`
|
||||||
|
}
|
||||||
const limited_string = is_limited ? (is_limited_unique ? "true (unique)" : "true") : "false";
|
});
|
||||||
|
|
||||||
embed = {
|
const item = await res.json();
|
||||||
color: 0x8aa2b3,
|
logger.debug(`[rbx] fetched item data (roblox) for "${argument}": ${JSON.stringify(item)}`);
|
||||||
author: {
|
|
||||||
name: message.author.username,
|
const resale_data = await resale_res.json();
|
||||||
icon_url: message.author.displayAvatarURL(),
|
logger.debug(`[rbx] fetched resale data for "${argument}": ${JSON.stringify(resale_data)}`);
|
||||||
},
|
|
||||||
description: `[${item.Name}](https://roblox.com/catalog/${argument}) ${hasAcronym ? item_e[1] : ""}\n-# *${item.Description}*`,
|
let itemsJson;
|
||||||
fields: [
|
try {
|
||||||
{ name: "id", value: `${item.AssetId}`, inline: true },
|
const itemsPath = path.resolve(process.cwd(), 'items.json');
|
||||||
{ name: "price", value: `${is_offsale ? "offsale" : item.PriceInRobux}`, inline: true },
|
const itemsRaw = fs.readFileSync(itemsPath, 'utf8');
|
||||||
{ name: "limited", value: `${limited_string}`, inline: true },
|
itemsJson = JSON.parse(itemsRaw);
|
||||||
{ name: "rap", value: `${is_limited_at_all ? resale_data.recentAveragePrice : "0"}`, inline: true },
|
if (itemsJson.items && itemsJson.items[argument]) {
|
||||||
{ name: "creator", value: `${item.Creator.Name}`, inline: true },
|
logger.debug(`[rbx] found item ${argument} in items.json: ${JSON.stringify(itemsJson.items[argument])}`);
|
||||||
],
|
}
|
||||||
thumbnail: {
|
} catch (e) {
|
||||||
url: item_thumb,
|
logger.warn(`[rbx] could not read items.json: ${e.message}`);
|
||||||
height: 420,
|
}
|
||||||
width: 420
|
|
||||||
},
|
let item_e = itemsJson.items[argument];
|
||||||
footer: {
|
|
||||||
text: `twitter @ ${message.guild.name}`,
|
var hasAcronym = false;
|
||||||
icon_url: client.user.displayAvatarURL(),
|
if (item_e[1] = "") {
|
||||||
},
|
hasAcronym = false;
|
||||||
timestamp: new Date(),
|
} else {
|
||||||
};
|
hasAcronym = true;
|
||||||
} catch (err) {
|
}
|
||||||
logger.error(`[rbx] failed to fetch item data for "${argument}":`, err);
|
|
||||||
embed = {
|
const item_thumb = await fetch_item_thumb(item.AssetId);
|
||||||
color: 0x8aa2b3,
|
const is_offsale = item.IsForSale;
|
||||||
author: {
|
|
||||||
name: message.author.username,
|
const is_limited = item.IsLimited;
|
||||||
icon_url: message.author.displayAvatarURL(),
|
const is_limited_unique = item.IsLimitedUnique;
|
||||||
},
|
|
||||||
description: `<:no:1481811955592466492> could not fetch data for item "${argument}"!`,
|
const is_limited_at_all = is_limited || is_limited_unique;
|
||||||
footer: {
|
|
||||||
text: `twitter @ ${message.guild.name}`,
|
const limited_string = is_limited ? (is_limited_unique ? "true (unique)" : "true") : "false";
|
||||||
icon_url: client.user.displayAvatarURL(),
|
|
||||||
},
|
embed = {
|
||||||
timestamp: new Date(),
|
color: 0x8aa2b3,
|
||||||
}
|
author: {
|
||||||
}
|
name: message.author.username,
|
||||||
} else if (subcommand === 'group') {
|
icon_url: message.author.displayAvatarURL(),
|
||||||
try {
|
},
|
||||||
const res = await fetch(`https://groups.roproxy.com/v1/groups/${argument}`);
|
description: `[${item.Name}](https://roblox.com/catalog/${argument}) ${hasAcronym ? item_e[1] : ""}\n-# *${item.Description}*`,
|
||||||
const p_res = await fetch(`https://thumbnails.roproxy.com/v1/groups/icons?groupIds=${argument}&size=420x420&format=Png&isCircular=false`);
|
fields: [
|
||||||
|
{ name: "id", value: `${item.AssetId}`, inline: true },
|
||||||
if (!res.ok) throw new Error();
|
{ name: "price", value: `${is_offsale ? "offsale" : item.PriceInRobux}`, inline: true },
|
||||||
if (!p_res.ok) throw new Error();
|
{ name: "limited", value: `${limited_string}`, inline: true },
|
||||||
|
{ name: "rap", value: `${is_limited_at_all ? resale_data.recentAveragePrice : "0"}`, inline: true },
|
||||||
const group = await res.json();
|
{ name: "creator", value: `${item.Creator.Name}`, inline: true },
|
||||||
const p_json = await p_res.json();
|
],
|
||||||
logger.debug(`${JSON.stringify(p_json)}`);
|
thumbnail: {
|
||||||
const thumb = (p_json && p_json.data && p_json.data[0]) ? p_json.data[0].imageUrl : null;
|
url: item_thumb,
|
||||||
|
height: 420,
|
||||||
embed = {
|
width: 420
|
||||||
color: 0x8aa2b3,
|
},
|
||||||
author: {
|
footer: {
|
||||||
name: message.author.username,
|
text: `twitter @ ${message.guild.name}`,
|
||||||
icon_url: message.author.displayAvatarURL(),
|
icon_url: client.user.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
description: `**[${group.name}](https://roblox.com/communities/${argument})**\n-# *${group.description || "no description"}*`,
|
timestamp: new Date(),
|
||||||
thumbnail: {
|
};
|
||||||
url: thumb,
|
} catch (err) {
|
||||||
height: 420,
|
logger.error(`[rbx] failed to fetch item data for "${argument}":`, err);
|
||||||
width: 420
|
embed = {
|
||||||
},
|
color: 0x8aa2b3,
|
||||||
fields: [
|
author: {
|
||||||
{ name: "members", value: `${group.memberCount}`, inline: true },
|
name: message.author.username,
|
||||||
{ name: "owner", value: `${group.owner.username}`, inline: true },
|
icon_url: message.author.displayAvatarURL(),
|
||||||
{ name: "shout", value: `${group.shout}`, inline: true },
|
},
|
||||||
{ name: "open", value: `${group.publicEntryAllowed}`, inline: true },
|
description: `<:no:1481811955592466492> could not fetch data for item "${argument}"!`,
|
||||||
{ name: "verified", value: `${group.hasVerifiedBadge}`, inline: true },
|
footer: {
|
||||||
],
|
text: `twitter @ ${message.guild.name}`,
|
||||||
footer: {
|
icon_url: client.user.displayAvatarURL(),
|
||||||
text: `twitter @ ${message.guild.name}`,
|
},
|
||||||
icon_url: client.user.displayAvatarURL(),
|
timestamp: new Date(),
|
||||||
},
|
}
|
||||||
timestamp: new Date(),
|
}
|
||||||
};
|
} else if (subcommand === 'group') {
|
||||||
} catch (err) {
|
try {
|
||||||
logger.error(`[rbx] failed to fetch group data for "${argument}":`, err);
|
const res = await fetch(`https://groups.roproxy.com/v1/groups/${argument}`);
|
||||||
embed.title = 'Error';
|
const p_res = await fetch(`https://thumbnails.roproxy.com/v1/groups/icons?groupIds=${argument}&size=420x420&format=Png&isCircular=false`);
|
||||||
embed.description = 'Failed to fetch group data.';
|
|
||||||
}
|
if (!res.ok) throw new Error();
|
||||||
} else if (subcommand === 'game') {
|
if (!p_res.ok) throw new Error();
|
||||||
try {
|
|
||||||
const res = await fetch(`https://games.roproxy.com/v1/games?universeIds=${argument}`);
|
const group = await res.json();
|
||||||
if (!res.ok) throw new Error();
|
const p_json = await p_res.json();
|
||||||
const data = await res.json();
|
logger.debug(`${JSON.stringify(p_json)}`);
|
||||||
if (!data.data || !data.data[0]) {
|
const thumb = (p_json && p_json.data && p_json.data[0]) ? p_json.data[0].imageUrl : null;
|
||||||
embed.title = 'Game Not Found';
|
|
||||||
embed.description = `Could not find a Roblox game with the universe ID **${argument}**.`;
|
embed = {
|
||||||
} else {
|
color: 0x8aa2b3,
|
||||||
const game = data.data[0];
|
author: {
|
||||||
embed.title = `Roblox Game: ${game.name}`;
|
name: message.author.username,
|
||||||
embed.description = game.description || 'No description.';
|
icon_url: message.author.displayAvatarURL(),
|
||||||
embed.thumbnail.url = `https://www.roproxy.com/asset-thumbnail/image?assetId=${game.rootPlaceId}&width=420&height=420&format=png`;
|
},
|
||||||
embed.fields = [
|
description: `**[${group.name}](https://roblox.com/communities/${argument})**\n-# *${group.description || "no description"}*`,
|
||||||
{ name: 'Creator', value: game.creator.name, inline: true },
|
thumbnail: {
|
||||||
{ name: 'Playing', value: game.playing.toLocaleString(), inline: true },
|
url: thumb,
|
||||||
{ name: 'Visits', value: game.visits.toLocaleString(), inline: true }
|
height: 420,
|
||||||
];
|
width: 420
|
||||||
}
|
},
|
||||||
} catch (err) {
|
fields: [
|
||||||
embed.title = 'Error';
|
{ name: "members", value: `${group.memberCount}`, inline: true },
|
||||||
embed.description = 'Failed to fetch game data.';
|
{ name: "owner", value: `${group.owner.username}`, inline: true },
|
||||||
}
|
{ name: "shout", value: `${group.shout}`, inline: true },
|
||||||
}/* else {
|
{ name: "open", value: `${group.publicEntryAllowed}`, inline: true },
|
||||||
embed.title = 'invalid subcommand';
|
{ name: "verified", value: `${group.hasVerifiedBadge}`, inline: true },
|
||||||
embed.description = 'Valid subcommands: `user`, `item`, `group`, `game`';
|
],
|
||||||
}*/
|
footer: {
|
||||||
|
text: `twitter @ ${message.guild.name}`,
|
||||||
await sent.edit({ content: null, embeds: [embed] });
|
icon_url: client.user.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
};
|
timestamp: new Date(),
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
logger.error(`[rbx] failed to fetch group data for "${argument}":`, err);
|
||||||
|
embed.title = 'Error';
|
||||||
|
embed.description = 'Failed to fetch group data.';
|
||||||
|
}
|
||||||
|
} else if (subcommand === 'game') {
|
||||||
|
try {
|
||||||
|
const res = await fetch(`https://games.roproxy.com/v1/games?universeIds=${argument}`);
|
||||||
|
if (!res.ok) throw new Error();
|
||||||
|
const data = await res.json();
|
||||||
|
if (!data.data || !data.data[0]) {
|
||||||
|
embed.title = 'Game Not Found';
|
||||||
|
embed.description = `Could not find a Roblox game with the universe ID **${argument}**.`;
|
||||||
|
} else {
|
||||||
|
const game = data.data[0];
|
||||||
|
embed.title = `Roblox Game: ${game.name}`;
|
||||||
|
embed.description = game.description || 'No description.';
|
||||||
|
embed.thumbnail.url = `https://www.roproxy.com/asset-thumbnail/image?assetId=${game.rootPlaceId}&width=420&height=420&format=png`;
|
||||||
|
embed.fields = [
|
||||||
|
{ name: 'Creator', value: game.creator.name, inline: true },
|
||||||
|
{ name: 'Playing', value: game.playing.toLocaleString(), inline: true },
|
||||||
|
{ name: 'Visits', value: game.visits.toLocaleString(), inline: true }
|
||||||
|
];
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
embed.title = 'Error';
|
||||||
|
embed.description = 'Failed to fetch game data.';
|
||||||
|
}
|
||||||
|
}/* else {
|
||||||
|
embed.title = 'invalid subcommand';
|
||||||
|
embed.description = 'Valid subcommands: `user`, `item`, `group`, `game`';
|
||||||
|
}*/
|
||||||
|
|
||||||
|
await sent.edit({ content: null, embeds: [embed] });
|
||||||
|
},
|
||||||
|
};
|
||||||
+76
-76
@@ -1,76 +1,76 @@
|
|||||||
const { EmbedBuilder } = require('discord.js');
|
const { EmbedBuilder } = require('discord.js');
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
name: 'help',
|
name: 'help',
|
||||||
description: 'lists all available commands or shows info about a specific one',
|
description: 'lists all available commands or shows info about a specific one',
|
||||||
aliases: ['h', 'commands'],
|
aliases: ['h', 'commands'],
|
||||||
usage: 'help [command]',
|
usage: 'help [command]',
|
||||||
|
|
||||||
execute(client, message, args) {
|
execute(client, message, args) {
|
||||||
var embed;
|
var embed;
|
||||||
const prefix = process.env.PREFIX || '!';
|
const prefix = process.env.PREFIX || '!';
|
||||||
|
|
||||||
// Show info for a specific command
|
// Show info for a specific command
|
||||||
if (args.length > 0) {
|
if (args.length > 0) {
|
||||||
const name = args[0].toLowerCase();
|
const name = args[0].toLowerCase();
|
||||||
const command = client.commands.get(name);
|
const command = client.commands.get(name);
|
||||||
|
|
||||||
if (!command) {
|
if (!command) {
|
||||||
return message.reply(`no command found for \`${name}\`.`);
|
return message.reply(`no command found for \`${name}\`.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
embed = {
|
embed = {
|
||||||
color: 0x8aa2b3,
|
color: 0x8aa2b3,
|
||||||
title: '',
|
title: '',
|
||||||
author: {
|
author: {
|
||||||
name: message.author.username,
|
name: message.author.username,
|
||||||
icon_url: message.author.displayAvatarURL(),
|
icon_url: message.author.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
description: `**${prefix}${command.name}**\n-# ${command.description || 'no description'}`,
|
description: `**${prefix}${command.name}**\n-# ${command.description || 'no description'}`,
|
||||||
fields: [
|
fields: [
|
||||||
{ name: 'aliases', value: command.aliases.map((a) => `\`${prefix}${a}\``).join(', ') },
|
{ name: 'aliases', value: command.aliases.map((a) => `\`${prefix}${a}\``).join(', ') },
|
||||||
{ name: 'usage', value: `\`${prefix}${command.usage}\`` }
|
{ name: 'usage', value: `\`${prefix}${command.usage}\`` }
|
||||||
],
|
],
|
||||||
footer: {
|
footer: {
|
||||||
text: `twitter @ ${message.guild.name}`,
|
text: `twitter @ ${message.guild.name}`,
|
||||||
icon_url: client.user.displayAvatarURL(),
|
icon_url: client.user.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
timestamp: new Date(),
|
timestamp: new Date(),
|
||||||
};
|
};
|
||||||
|
|
||||||
return message.reply({ embeds: [embed] });
|
return message.reply({ embeds: [embed] });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build a deduplicated command list (ignore aliases pointing to the same command)
|
// Build a deduplicated command list (ignore aliases pointing to the same command)
|
||||||
const seen = new Set();
|
const seen = new Set();
|
||||||
const commandList = [];
|
const commandList = [];
|
||||||
|
|
||||||
for (const command of client.commands.values()) {
|
for (const command of client.commands.values()) {
|
||||||
if (seen.has(command.name)) continue;
|
if (seen.has(command.name)) continue;
|
||||||
seen.add(command.name);
|
seen.add(command.name);
|
||||||
commandList.push(`\`${prefix}${command.name}\` — ${command.description || 'no description'}`);
|
commandList.push(`\`${prefix}${command.name}\` — ${command.description || 'no description'}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
embed = {
|
embed = {
|
||||||
color: 0x8aa2b3,
|
color: 0x8aa2b3,
|
||||||
title: '',
|
title: '',
|
||||||
author: {
|
author: {
|
||||||
name: message.author.username,
|
name: message.author.username,
|
||||||
icon_url: message.author.displayAvatarURL(),
|
icon_url: message.author.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
description: `-# use ${prefix}help <command> for more details`,
|
description: `-# use ${prefix}help <command> for more details`,
|
||||||
fields: [
|
fields: [
|
||||||
{ name: 'commands', value: commandList.join('\n') },
|
{ name: 'commands', value: commandList.join('\n') },
|
||||||
],
|
],
|
||||||
footer: {
|
footer: {
|
||||||
text: `twitter @ ${message.guild.name}`,
|
text: `twitter @ ${message.guild.name}`,
|
||||||
icon_url: client.user.displayAvatarURL(),
|
icon_url: client.user.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
timestamp: new Date(),
|
timestamp: new Date(),
|
||||||
};
|
};
|
||||||
|
|
||||||
return message.reply({ embeds: [embed] });
|
return message.reply({ embeds: [embed] });
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const { time } = require("discord.js");
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
name: 'autoban',
|
||||||
|
description: `automatically ban a user if they join the server`,
|
||||||
|
aliases: ['ab', 'banish'],
|
||||||
|
usage: 'ban <user> [reason] [duration]',
|
||||||
|
|
||||||
|
async execute(client, message, args) {
|
||||||
|
if (!message.member.permissions.has('BanMembers')) {
|
||||||
|
return message.reply({
|
||||||
|
content: null, embeds: [{
|
||||||
|
color: 0x8aa2b3,
|
||||||
|
author: {
|
||||||
|
name: message.author.username,
|
||||||
|
icon_url: message.author.displayAvatarURL(),
|
||||||
|
},
|
||||||
|
description: '<:no:1481811955592466492> you do not have permission to use this command!',
|
||||||
|
footer: {
|
||||||
|
text: `twitter @ ${message.guild.name}`,
|
||||||
|
icon_url: client.user.displayAvatarURL(),
|
||||||
|
},
|
||||||
|
timestamp: new Date(),
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const user = message.mentions.users.first() || await client.users.fetch(args[0]).catch(() => null);
|
||||||
|
if (!user) {
|
||||||
|
return message.reply({
|
||||||
|
content: null, embeds: [{
|
||||||
|
color: 0x8aa2b3,
|
||||||
|
author: {
|
||||||
|
name: message.author.username,
|
||||||
|
icon_url: message.author.displayAvatarURL(),
|
||||||
|
},
|
||||||
|
description: '<:no:1481811955592466492> please specify a user to autoban!',
|
||||||
|
footer: {
|
||||||
|
text: `twitter @ ${message.guild.name}`,
|
||||||
|
icon_url: client.user.displayAvatarURL(),
|
||||||
|
},
|
||||||
|
timestamp: new Date(),
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const reason = args.slice(1).join(' ') || 'autobanned (twitter)';
|
||||||
|
|
||||||
|
const dbPath = path.join(__dirname, '..', '..', '..', 'db.json');
|
||||||
|
|
||||||
|
let db = {};
|
||||||
|
if (fs.existsSync(dbPath)) {
|
||||||
|
db = JSON.parse(fs.readFileSync(dbPath, 'utf8'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!db.autobans) {
|
||||||
|
db.autobans = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
db.autobans[message.guild.id] = user.id;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await fs.writeFileSync(dbPath, JSON.stringify(db, null, 2));
|
||||||
|
message.reply({
|
||||||
|
content: null, embeds: [{
|
||||||
|
color: 0x8aa2b3,
|
||||||
|
author: {
|
||||||
|
name: message.author.username,
|
||||||
|
icon_url: message.author.displayAvatarURL(),
|
||||||
|
},
|
||||||
|
description: `<:check:1481811973447356496> ${user.username} has been added to the autoban list!`,
|
||||||
|
footer: {
|
||||||
|
text: `twitter @ ${message.guild.name}`,
|
||||||
|
icon_url: client.user.displayAvatarURL(),
|
||||||
|
},
|
||||||
|
timestamp: new Date(),
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
message.reply({
|
||||||
|
content: null, embeds: [{
|
||||||
|
color: 0x8aa2b3,
|
||||||
|
author: {
|
||||||
|
name: message.author.username,
|
||||||
|
icon_url: message.author.displayAvatarURL(),
|
||||||
|
},
|
||||||
|
description: '<:no:1481811955592466492> an error occurred while trying to add the user to the autoban list!',
|
||||||
|
footer: {
|
||||||
|
text: `twitter @ ${message.guild.name}`,
|
||||||
|
icon_url: client.user.displayAvatarURL(),
|
||||||
|
},
|
||||||
|
timestamp: new Date(),
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -1,88 +1,88 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const { time } = require("discord.js");
|
const { time } = require("discord.js");
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
name: 'ban',
|
name: 'ban',
|
||||||
description: `ban a user from the current server`,
|
description: `ban a user from the current server`,
|
||||||
aliases: ['banish'],
|
aliases: ['b'],
|
||||||
usage: 'ban <user> [reason] [duration]',
|
usage: 'ban <user> [reason] [duration]',
|
||||||
|
|
||||||
async execute(client, message, args) {
|
async execute(client, message, args) {
|
||||||
if (!message.member.permissions.has('BanMembers')) {
|
if (!message.member.permissions.has('BanMembers')) {
|
||||||
return message.reply({
|
return message.reply({
|
||||||
content: null, embeds: [{
|
content: null, embeds: [{
|
||||||
color: 0x8aa2b3,
|
color: 0x8aa2b3,
|
||||||
author: {
|
author: {
|
||||||
name: message.author.username,
|
name: message.author.username,
|
||||||
icon_url: message.author.displayAvatarURL(),
|
icon_url: message.author.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
description: '<:no:1481811955592466492> you do not have permission to use this command!',
|
description: '<:no:1481811955592466492> you do not have permission to use this command!',
|
||||||
footer: {
|
footer: {
|
||||||
text: `twitter @ ${message.guild.name}`,
|
text: `twitter @ ${message.guild.name}`,
|
||||||
icon_url: client.user.displayAvatarURL(),
|
icon_url: client.user.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
timestamp: new Date(),
|
timestamp: new Date(),
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const user = message.mentions.users.first() || client.users.cache.get(args[0]);
|
const user = message.mentions.users.first() || client.users.cache.get(args[0]);
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return message.reply({
|
return message.reply({
|
||||||
content: null, embeds: [{
|
content: null, embeds: [{
|
||||||
color: 0x8aa2b3,
|
color: 0x8aa2b3,
|
||||||
author: {
|
author: {
|
||||||
name: message.author.username,
|
name: message.author.username,
|
||||||
icon_url: message.author.displayAvatarURL(),
|
icon_url: message.author.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
description: '<:no:1481811955592466492> please specify a user to ban!',
|
description: '<:no:1481811955592466492> please specify a user to ban!',
|
||||||
footer: {
|
footer: {
|
||||||
text: `twitter @ ${message.guild.name}`,
|
text: `twitter @ ${message.guild.name}`,
|
||||||
icon_url: client.user.displayAvatarURL(),
|
icon_url: client.user.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
timestamp: new Date(),
|
timestamp: new Date(),
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const reason = args.slice(1).join(' ') || 'no reason provided (twitter)';
|
const reason = args.slice(1).join(' ') || 'no reason provided (twitter)';
|
||||||
const duration = args[2] ? parseInt(args[2]) : null;
|
const duration = args[2] ? parseInt(args[2]) : null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await message.guild.members.ban(user, { reason });
|
await message.guild.members.ban(user, { reason });
|
||||||
message.reply({
|
message.reply({
|
||||||
content: null, embeds: [{
|
content: null, embeds: [{
|
||||||
color: 0x8aa2b3,
|
color: 0x8aa2b3,
|
||||||
author: {
|
author: {
|
||||||
name: message.author.username,
|
name: message.author.username,
|
||||||
icon_url: message.author.displayAvatarURL(),
|
icon_url: message.author.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
description: `<:check:1481811973447356496> ${user.username} has been banned!`,
|
description: `<:check:1481811973447356496> ${user.username} has been banned!`,
|
||||||
footer: {
|
footer: {
|
||||||
text: `twitter @ ${message.guild.name}`,
|
text: `twitter @ ${message.guild.name}`,
|
||||||
icon_url: client.user.displayAvatarURL(),
|
icon_url: client.user.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
timestamp: new Date(),
|
timestamp: new Date(),
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
message.reply({
|
message.reply({
|
||||||
content: null, embeds: [{
|
content: null, embeds: [{
|
||||||
color: 0x8aa2b3,
|
color: 0x8aa2b3,
|
||||||
author: {
|
author: {
|
||||||
name: message.author.username,
|
name: message.author.username,
|
||||||
icon_url: message.author.displayAvatarURL(),
|
icon_url: message.author.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
description: '<:no:1481811955592466492> an error occurred while trying to ban the user!',
|
description: '<:no:1481811955592466492> an error occurred while trying to ban the user!',
|
||||||
footer: {
|
footer: {
|
||||||
text: `twitter @ ${message.guild.name}`,
|
text: `twitter @ ${message.guild.name}`,
|
||||||
icon_url: client.user.displayAvatarURL(),
|
icon_url: client.user.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
timestamp: new Date(),
|
timestamp: new Date(),
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -1,88 +1,88 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const { time } = require("discord.js");
|
const { time } = require("discord.js");
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
name: 'kick',
|
name: 'kick',
|
||||||
description: `kick a user from the current server`,
|
description: `kick a user from the current server`,
|
||||||
aliases: ['kick'],
|
aliases: ['kick'],
|
||||||
usage: 'kick <user> [reason]',
|
usage: 'kick <user> [reason]',
|
||||||
|
|
||||||
async execute(client, message, args) {
|
async execute(client, message, args) {
|
||||||
if (!message.member.permissions.has('KickMembers')) {
|
if (!message.member.permissions.has('KickMembers')) {
|
||||||
return message.reply({
|
return message.reply({
|
||||||
content: null, embeds: [{
|
content: null, embeds: [{
|
||||||
color: 0x8aa2b3,
|
color: 0x8aa2b3,
|
||||||
author: {
|
author: {
|
||||||
name: message.author.username,
|
name: message.author.username,
|
||||||
icon_url: message.author.displayAvatarURL(),
|
icon_url: message.author.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
description: '<:no:1481811955592466492> you do not have permission to use this command!',
|
description: '<:no:1481811955592466492> you do not have permission to use this command!',
|
||||||
footer: {
|
footer: {
|
||||||
text: `twitter @ ${message.guild.name}`,
|
text: `twitter @ ${message.guild.name}`,
|
||||||
icon_url: client.user.displayAvatarURL(),
|
icon_url: client.user.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
timestamp: new Date(),
|
timestamp: new Date(),
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const user = message.mentions.users.first() || client.users.cache.get(args[0]);
|
const user = message.mentions.users.first() || client.users.cache.get(args[0]);
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return message.reply({
|
return message.reply({
|
||||||
content: null, embeds: [{
|
content: null, embeds: [{
|
||||||
color: 0x8aa2b3,
|
color: 0x8aa2b3,
|
||||||
author: {
|
author: {
|
||||||
name: message.author.username,
|
name: message.author.username,
|
||||||
icon_url: message.author.displayAvatarURL(),
|
icon_url: message.author.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
description: '<:no:1481811955592466492> please specify a user to ban!',
|
description: '<:no:1481811955592466492> please specify a user to ban!',
|
||||||
footer: {
|
footer: {
|
||||||
text: `twitter @ ${message.guild.name}`,
|
text: `twitter @ ${message.guild.name}`,
|
||||||
icon_url: client.user.displayAvatarURL(),
|
icon_url: client.user.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
timestamp: new Date(),
|
timestamp: new Date(),
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const reason = args.slice(1).join(' ') || 'no reason provided (twitter)';
|
const reason = args.slice(1).join(' ') || 'no reason provided (twitter)';
|
||||||
const duration = args[2] ? parseInt(args[2]) : null;
|
const duration = args[2] ? parseInt(args[2]) : null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await message.guild.members.kick(user, { reason });
|
await message.guild.members.kick(user, { reason });
|
||||||
message.reply({
|
message.reply({
|
||||||
content: null, embeds: [{
|
content: null, embeds: [{
|
||||||
color: 0x8aa2b3,
|
color: 0x8aa2b3,
|
||||||
author: {
|
author: {
|
||||||
name: message.author.username,
|
name: message.author.username,
|
||||||
icon_url: message.author.displayAvatarURL(),
|
icon_url: message.author.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
description: `<:check:1481811973447356496> ${user.username} has been kicked!`,
|
description: `<:check:1481811973447356496> ${user.username} has been kicked!`,
|
||||||
footer: {
|
footer: {
|
||||||
text: `twitter @ ${message.guild.name}`,
|
text: `twitter @ ${message.guild.name}`,
|
||||||
icon_url: client.user.displayAvatarURL(),
|
icon_url: client.user.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
timestamp: new Date(),
|
timestamp: new Date(),
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
message.reply({
|
message.reply({
|
||||||
content: null, embeds: [{
|
content: null, embeds: [{
|
||||||
color: 0x8aa2b3,
|
color: 0x8aa2b3,
|
||||||
author: {
|
author: {
|
||||||
name: message.author.username,
|
name: message.author.username,
|
||||||
icon_url: message.author.displayAvatarURL(),
|
icon_url: message.author.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
description: '<:no:1481811955592466492> an error occurred while trying to ban the user!',
|
description: '<:no:1481811955592466492> an error occurred while trying to ban the user!',
|
||||||
footer: {
|
footer: {
|
||||||
text: `twitter @ ${message.guild.name}`,
|
text: `twitter @ ${message.guild.name}`,
|
||||||
icon_url: client.user.displayAvatarURL(),
|
icon_url: client.user.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
timestamp: new Date(),
|
timestamp: new Date(),
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -1,84 +1,84 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const { time } = require("discord.js");
|
const { time } = require("discord.js");
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
name: 'autorole',
|
name: 'autorole',
|
||||||
description: `assign a role to new members when they join the server`,
|
description: `assign a role to new members when they join the server`,
|
||||||
aliases: ['ar'],
|
aliases: ['ar'],
|
||||||
usage: 'autorole <role>',
|
usage: 'autorole <role>',
|
||||||
|
|
||||||
async execute(client, message, args) {
|
async execute(client, message, args) {
|
||||||
if (!message.member.permissions.has('Administrator')) {
|
if (!message.member.permissions.has('Administrator')) {
|
||||||
return message.reply({
|
return message.reply({
|
||||||
content: null, embeds: [{
|
content: null, embeds: [{
|
||||||
color: 0x8aa2b3,
|
color: 0x8aa2b3,
|
||||||
author: {
|
author: {
|
||||||
name: message.author.username,
|
name: message.author.username,
|
||||||
icon_url: message.author.displayAvatarURL(),
|
icon_url: message.author.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
description: '<:no:1481811955592466492> you do not have permission to use this command!',
|
description: '<:no:1481811955592466492> you do not have permission to use this command!',
|
||||||
footer: {
|
footer: {
|
||||||
text: `twitter @ ${message.guild.name}`,
|
text: `twitter @ ${message.guild.name}`,
|
||||||
icon_url: client.user.displayAvatarURL(),
|
icon_url: client.user.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
timestamp: new Date(),
|
timestamp: new Date(),
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const role = message.mentions.roles.first() || message.guild.roles.cache.get(args[0]);
|
const role = message.mentions.roles.first() || message.guild.roles.cache.get(args[0]);
|
||||||
|
|
||||||
if (!role) {
|
if (!role) {
|
||||||
return message.reply({
|
return message.reply({
|
||||||
content: null, embeds: [{
|
content: null, embeds: [{
|
||||||
color: 0x8aa2b3,
|
color: 0x8aa2b3,
|
||||||
author: {
|
author: {
|
||||||
name: message.author.username,
|
name: message.author.username,
|
||||||
icon_url: message.author.displayAvatarURL(),
|
icon_url: message.author.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
description: '<:no:1481811955592466492> please provide a valid role!',
|
description: '<:no:1481811955592466492> please provide a valid role!',
|
||||||
footer: {
|
footer: {
|
||||||
text: `twitter @ ${message.guild.name}`,
|
text: `twitter @ ${message.guild.name}`,
|
||||||
icon_url: client.user.displayAvatarURL(),
|
icon_url: client.user.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
timestamp: new Date(),
|
timestamp: new Date(),
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// add the role to a json file for the guild and save it to be used when new members join (if the role is already in the database, update it to the new role)
|
// add the role to a json file for the guild and save it to be used when new members join (if the role is already in the database, update it to the new role)
|
||||||
const dbPath = path.join(__dirname, '..', '..', '..', 'db.json');
|
const dbPath = path.join(__dirname, '..', '..', '..', 'db.json');
|
||||||
|
|
||||||
let db = {};
|
let db = {};
|
||||||
if (fs.existsSync(dbPath)) {
|
if (fs.existsSync(dbPath)) {
|
||||||
db = JSON.parse(fs.readFileSync(dbPath, 'utf8'));
|
db = JSON.parse(fs.readFileSync(dbPath, 'utf8'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!db.autoroles) {
|
if (!db.autoroles) {
|
||||||
db.autoroles = {};
|
db.autoroles = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
db.autoroles[message.guild.id] = role.id;
|
db.autoroles[message.guild.id] = role.id;
|
||||||
|
|
||||||
fs.writeFileSync(dbPath, JSON.stringify(db, null, 2));
|
fs.writeFileSync(dbPath, JSON.stringify(db, null, 2));
|
||||||
|
|
||||||
message.reply({
|
message.reply({
|
||||||
content: null, embeds: [{
|
content: null, embeds: [{
|
||||||
color: 0x8aa2b3,
|
color: 0x8aa2b3,
|
||||||
author: {
|
author: {
|
||||||
name: message.author.username,
|
name: message.author.username,
|
||||||
icon_url: message.author.displayAvatarURL(),
|
icon_url: message.author.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
description: `<:check:1481811973447356496> "${role.name}" has been set as the autorole!`,
|
description: `<:check:1481811973447356496> "${role.name}" has been set as the autorole!`,
|
||||||
footer: {
|
footer: {
|
||||||
text: `twitter @ ${message.guild.name}`,
|
text: `twitter @ ${message.guild.name}`,
|
||||||
icon_url: client.user.displayAvatarURL(),
|
icon_url: client.user.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
timestamp: new Date(),
|
timestamp: new Date(),
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
+43
-43
@@ -1,43 +1,43 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const { time } = require("discord.js");
|
const { time } = require("discord.js");
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
name: 'ping',
|
name: 'ping',
|
||||||
description: `test the bot's latency to discord's servers and api`,
|
description: `test the bot's latency to discord's servers and api`,
|
||||||
aliases: ['pong'],
|
aliases: ['pong'],
|
||||||
usage: 'ping',
|
usage: 'ping',
|
||||||
|
|
||||||
async execute(client, message) {
|
async execute(client, message) {
|
||||||
const sent = await message.reply('pinging');
|
const sent = await message.reply('pinging');
|
||||||
const latency = sent.createdTimestamp - message.createdTimestamp;
|
const latency = sent.createdTimestamp - message.createdTimestamp;
|
||||||
const apiLatency = Math.round(client.ws.ping);
|
const apiLatency = Math.round(client.ws.ping);
|
||||||
|
|
||||||
const embed = {
|
const embed = {
|
||||||
color: 0x8aa2b3,
|
color: 0x8aa2b3,
|
||||||
title: '',
|
title: '',
|
||||||
author: {
|
author: {
|
||||||
name: message.author.username,
|
name: message.author.username,
|
||||||
icon_url: message.author.displayAvatarURL(),
|
icon_url: message.author.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
description: 'fuck you!!!! 🖕',
|
description: 'fuck you!!!! 🖕',
|
||||||
fields: [
|
fields: [
|
||||||
{ name: '# of cmds loaded', value: `**${client.commands.size}**`, inline: true },
|
{ name: '# of cmds loaded', value: `**${client.commands.size}**`, inline: true },
|
||||||
{ name: 'bot latency', value: `**${latency}ms**`, inline: true },
|
{ name: 'bot latency', value: `**${latency}ms**`, inline: true },
|
||||||
{ name: 'api latency', value: `**${apiLatency}ms**`, inline: true },
|
{ name: 'api latency', value: `**${apiLatency}ms**`, inline: true },
|
||||||
],
|
],
|
||||||
footer: {
|
footer: {
|
||||||
text: `twitter @ ${message.guild.name}`,
|
text: `twitter @ ${message.guild.name}`,
|
||||||
icon_url: client.user.displayAvatarURL(),
|
icon_url: client.user.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
timestamp: new Date(),
|
timestamp: new Date(),
|
||||||
thumbnail: {
|
thumbnail: {
|
||||||
url: client.user.displayAvatarURL(),
|
url: client.user.displayAvatarURL(),
|
||||||
height: 1024,
|
height: 1024,
|
||||||
width: 1024,
|
width: 1024,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
await sent.edit({ content: null, embeds: [embed] });
|
await sent.edit({ content: null, embeds: [embed] });
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
+61
-61
@@ -1,61 +1,61 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const { time } = require("discord.js");
|
const { time } = require("discord.js");
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
name: 'purge',
|
name: 'purge',
|
||||||
description: `delete a specified number of messages from the current channel`,
|
description: `delete a specified number of messages from the current channel`,
|
||||||
aliases: ['clear', 'p'],
|
aliases: ['clear', 'p'],
|
||||||
usage: 'purge <number>',
|
usage: 'purge <number>',
|
||||||
|
|
||||||
async execute(client, message) {
|
async execute(client, message) {
|
||||||
if (!message.member.permissions.has('ManageMessages')) {
|
if (!message.member.permissions.has('ManageMessages')) {
|
||||||
return message.reply({
|
return message.reply({
|
||||||
content: null, embeds: [{
|
content: null, embeds: [{
|
||||||
color: 0x8aa2b3,
|
color: 0x8aa2b3,
|
||||||
description: '<:no:1481811955592466492> you do not have permission to use this command!',
|
description: '<:no:1481811955592466492> you do not have permission to use this command!',
|
||||||
footer: {
|
footer: {
|
||||||
text: `twitter @ ${message.guild.name}`,
|
text: `twitter @ ${message.guild.name}`,
|
||||||
icon_url: client.user.displayAvatarURL(),
|
icon_url: client.user.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
timestamp: new Date(),
|
timestamp: new Date(),
|
||||||
}],
|
}],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const args = message.content.split(' ').slice(1);
|
const args = message.content.split(' ').slice(1);
|
||||||
const amount = parseInt(args[0]) + 1;
|
const amount = parseInt(args[0]) + 1;
|
||||||
|
|
||||||
if (isNaN(amount) || amount < 1 || amount > 100) {
|
if (isNaN(amount) || amount < 1 || amount > 100) {
|
||||||
return message.reply({
|
return message.reply({
|
||||||
content: null, embeds: [{
|
content: null, embeds: [{
|
||||||
color: 0x8aa2b3,
|
color: 0x8aa2b3,
|
||||||
description: '<:no:1481811955592466492> please provide a number between 1 and 100!',
|
description: '<:no:1481811955592466492> please provide a number between 1 and 100!',
|
||||||
footer: {
|
footer: {
|
||||||
text: `twitter @ ${message.guild.name}`,
|
text: `twitter @ ${message.guild.name}`,
|
||||||
icon_url: client.user.displayAvatarURL(),
|
icon_url: client.user.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
timestamp: new Date(),
|
timestamp: new Date(),
|
||||||
}],
|
}],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const deletedMessages = await message.channel.bulkDelete(amount, true);
|
const deletedMessages = await message.channel.bulkDelete(amount, true);
|
||||||
const reply = await message.channel.send({
|
const reply = await message.channel.send({
|
||||||
content: null, embeds: [{
|
content: null, embeds: [{
|
||||||
color: 0x8aa2b3,
|
color: 0x8aa2b3,
|
||||||
author: {
|
author: {
|
||||||
name: message.author.username,
|
name: message.author.username,
|
||||||
icon_url: message.author.displayAvatarURL(),
|
icon_url: message.author.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
description: `<:no:1481811955592466492> successfully deleted ${deletedMessages.size - 1} messages!`,
|
description: `<:no:1481811955592466492> successfully deleted ${deletedMessages.size - 1} messages!`,
|
||||||
footer: {
|
footer: {
|
||||||
text: `twitter @ ${message.guild.name}`,
|
text: `twitter @ ${message.guild.name}`,
|
||||||
icon_url: client.user.displayAvatarURL(),
|
icon_url: client.user.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
timestamp: new Date(),
|
timestamp: new Date(),
|
||||||
}],
|
}],
|
||||||
});
|
});
|
||||||
setTimeout(() => reply.delete().catch(() => { }), 5000);
|
setTimeout(() => reply.delete().catch(() => { }), 5000);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -1,33 +1,50 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const { Events } = require('discord.js');
|
const { Events } = require('discord.js');
|
||||||
const logger = require('../utils/logger');
|
const logger = require('../utils/logger');
|
||||||
|
|
||||||
module.exports = (client, member) => {
|
module.exports = (client, member) => {
|
||||||
const dbPath = path.join(__dirname, '..', '..', 'db.json');
|
const dbPath = path.join(__dirname, '..', '..', 'db.json');
|
||||||
const db = JSON.parse(fs.readFileSync(dbPath, 'utf8'));
|
const db = JSON.parse(fs.readFileSync(dbPath, 'utf8'));
|
||||||
const roleId = db.autoroles ? db.autoroles[member.guild.id] : null;
|
const roleId = db.autoroles ? db.autoroles[member.guild.id] : null;
|
||||||
|
|
||||||
logger.info(`member "${member.user.tag}" has joined guild "${member.guild.name}"`);
|
logger.info(`member "${member.user.tag}" has joined guild "${member.guild.name}"`);
|
||||||
|
|
||||||
// autorole
|
// autorole
|
||||||
{
|
{
|
||||||
if (!roleId) {
|
if (!roleId) {
|
||||||
logger.info(`no autorole is set up in "${member.guild.name}"`);
|
logger.info(`no autorole is set up in "${member.guild.name}"`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const role = member.guild.roles.cache.get(roleId);
|
const role = member.guild.roles.cache.get(roleId);
|
||||||
|
|
||||||
if (!role) {
|
if (!role) {
|
||||||
logger.error(`role with id "${roleId}" not found in guild "${member.guild.name}"`);
|
logger.error(`role with id "${roleId}" not found in guild "${member.guild.name}"`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
member.roles.add(role)
|
member.roles.add(role)
|
||||||
.then(() => logger.info(`assigned role "${role.name}" to user "${member.user.tag}"!`))
|
.then(() => logger.info(`assigned role "${role.name}" to user "${member.user.tag}"!`))
|
||||||
.catch(error => logger.error(`failed to assign role "${role.name}" to user "${member.user.tag}": ${error}`));
|
.catch(error => logger.error(`failed to assign role "${role.name}" to user "${member.user.tag}": ${error}`));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// autoban
|
||||||
|
{
|
||||||
|
const autoban = db.autobans ? db.autobans[member.guild.id] : null;
|
||||||
|
if (!autoban) {
|
||||||
|
logger.info(`no autoban is set up for ${member.user.tag} in "${member.guild.name}"`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (member.user.tag === autoban) {
|
||||||
|
member.ban({ reason: 'autobanned (twitter)' })
|
||||||
|
.then(() => logger.info(`autobanned user "${member.user.tag}" from guild "${member.guild.name}"`))
|
||||||
|
.catch(error => logger.error(`failed to autoban user "${member.user.tag}" from guild "${member.guild.name}": ${error}`));
|
||||||
|
} else {
|
||||||
|
logger.info(`user "${member.user.tag}" is not on the autoban list for "${member.guild.name}"`);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
+52
-52
@@ -1,52 +1,52 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const { Events } = require('discord.js');
|
const { Events } = require('discord.js');
|
||||||
const logger = require('../utils/logger');
|
const logger = require('../utils/logger');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
name: Events.MessageCreate,
|
name: Events.MessageCreate,
|
||||||
|
|
||||||
async execute(client, message) {
|
async execute(client, message) {
|
||||||
// Ignore bots and messages without the prefix
|
// Ignore bots and messages without the prefix
|
||||||
if (message.author.bot) return;
|
if (message.author.bot) return;
|
||||||
|
|
||||||
const prefix = process.env.PREFIX || '!';
|
const prefix = process.env.PREFIX || '!';
|
||||||
if (!message.content.startsWith(prefix)) return;
|
if (!message.content.startsWith(prefix)) return;
|
||||||
|
|
||||||
// Parse command name and arguments
|
// Parse command name and arguments
|
||||||
const args = message.content.slice(prefix.length).trim().split(/\s+/);
|
const args = message.content.slice(prefix.length).trim().split(/\s+/);
|
||||||
const commandName = args.shift().toLowerCase();
|
const commandName = args.shift().toLowerCase();
|
||||||
|
|
||||||
const command = client.commands.get(commandName);
|
const command = client.commands.get(commandName);
|
||||||
if (!command) return;
|
if (!command) return;
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
`[command] "${commandName}" used by ${message.author.tag} (${message.author.id})` +
|
`[command] "${commandName}" used by ${message.author.tag} (${message.author.id})` +
|
||||||
` in ${message.guild ? `#${message.channel.name} (${message.guild.name})` : 'dms'}`,
|
` in ${message.guild ? `#${message.channel.name} (${message.guild.name})` : 'dms'}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await command.execute(client, message, args);
|
await command.execute(client, message, args);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error(`[command] error executing "${commandName}":`, err);
|
logger.error(`[command] error executing "${commandName}":`, err);
|
||||||
await message
|
await message
|
||||||
.reply({
|
.reply({
|
||||||
content: null, embeds: [{
|
content: null, embeds: [{
|
||||||
color: 0x8aa2b3,
|
color: 0x8aa2b3,
|
||||||
title: '',
|
title: '',
|
||||||
author: {
|
author: {
|
||||||
name: message.author.username,
|
name: message.author.username,
|
||||||
icon_url: message.author.displayAvatarURL(),
|
icon_url: message.author.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
description: '<:no:1481811955592466492> an error occurred while executing that command!',
|
description: '<:no:1481811955592466492> an error occurred while executing that command!',
|
||||||
footer: {
|
footer: {
|
||||||
text: `${message.author.username} @ twitter`,
|
text: `${message.author.username} @ twitter`,
|
||||||
icon_url: message.author.displayAvatarURL(),
|
icon_url: message.author.displayAvatarURL(),
|
||||||
},
|
},
|
||||||
timestamp: new Date(),
|
timestamp: new Date(),
|
||||||
}]
|
}]
|
||||||
})
|
})
|
||||||
.catch(() => null);
|
.catch(() => null);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
+36
-36
@@ -1,36 +1,36 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const { ActivityType, Events } = require('discord.js');
|
const { ActivityType, Events } = require('discord.js');
|
||||||
const logger = require('../utils/logger');
|
const logger = require('../utils/logger');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
name: Events.ClientReady,
|
name: Events.ClientReady,
|
||||||
once: true,
|
once: true,
|
||||||
|
|
||||||
execute(client) {
|
execute(client) {
|
||||||
const db_path = path.join(process.cwd(), 'db.json');
|
const db_path = path.join(process.cwd(), 'db.json');
|
||||||
if (!fs.existsSync(db_path)) {
|
if (!fs.existsSync(db_path)) {
|
||||||
fs.writeFileSync(db_path, JSON.stringify({}, null, 2));
|
fs.writeFileSync(db_path, JSON.stringify({}, null, 2));
|
||||||
logger.info('[db] created db.json');
|
logger.info('[db] created db.json');
|
||||||
}
|
}
|
||||||
|
|
||||||
const db = JSON.parse(fs.readFileSync(db_path, 'utf8'));
|
const db = JSON.parse(fs.readFileSync(db_path, 'utf8'));
|
||||||
const variables = Object.keys(db);
|
const variables = Object.keys(db);
|
||||||
logger.info(`[db] loaded variables from db.json: ${variables.length > 0 ? variables.join(', ') : 'none'}`);
|
logger.info(`[db] loaded variables from db.json: ${variables.length > 0 ? variables.join(', ') : 'none'}`);
|
||||||
|
|
||||||
// cache rolimons item list
|
// cache rolimons item list
|
||||||
fetch('https://api.rolimons.com/items/v2/itemdetails')
|
fetch('https://api.rolimons.com/items/v2/itemdetails')
|
||||||
.then(res => res.ok ? res.json() : Promise.reject(new Error('Failed to fetch rolimons item list')))
|
.then(res => res.ok ? res.json() : Promise.reject(new Error('Failed to fetch rolimons item list')))
|
||||||
.then(data => {
|
.then(data => {
|
||||||
fs.writeFileSync(path.join(process.cwd(), 'items.json'), JSON.stringify(data, null, 2));
|
fs.writeFileSync(path.join(process.cwd(), 'items.json'), JSON.stringify(data, null, 2));
|
||||||
})
|
})
|
||||||
.catch(err => logger.error('[ready] error fetching rolimons item list:', err));
|
.catch(err => logger.error('[ready] error fetching rolimons item list:', err));
|
||||||
|
|
||||||
logger.info(`[ready] logged in as ${client.user.tag} (${client.user.id})`);
|
logger.info(`[ready] logged in as ${client.user.tag} (${client.user.id})`);
|
||||||
logger.info(`[ready] serving ${client.guilds.cache.size} guild(s)`);
|
logger.info(`[ready] serving ${client.guilds.cache.size} guild(s)`);
|
||||||
|
|
||||||
client.user.setActivity(`watching over ${client.guilds.cache.size} servers`, { type: ActivityType.Watching });
|
client.user.setActivity(`watching over ${client.guilds.cache.size} servers`, { type: ActivityType.Watching });
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -1,65 +1,65 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const logger = require('../utils/logger');
|
const logger = require('../utils/logger');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads all command files from src/commands and registers them on the client.
|
* Loads all command files from src/commands and registers them on the client.
|
||||||
* Each command file must export: { name, description, aliases?, usage?, execute }
|
* Each command file must export: { name, description, aliases?, usage?, execute }
|
||||||
*
|
*
|
||||||
* @param {import('discord.js').Client} client
|
* @param {import('discord.js').Client} client
|
||||||
*/
|
*/
|
||||||
function loadCommands(client) {
|
function loadCommands(client) {
|
||||||
const commandsPath = path.join(__dirname, '..', 'commands');
|
const commandsPath = path.join(__dirname, '..', 'commands');
|
||||||
|
|
||||||
// Recursively get all .js files in commandsPath
|
// Recursively get all .js files in commandsPath
|
||||||
function getAllCommandFiles(dir) {
|
function getAllCommandFiles(dir) {
|
||||||
let results = [];
|
let results = [];
|
||||||
const list = fs.readdirSync(dir, { withFileTypes: true });
|
const list = fs.readdirSync(dir, { withFileTypes: true });
|
||||||
for (const entry of list) {
|
for (const entry of list) {
|
||||||
const fullPath = path.join(dir, entry.name);
|
const fullPath = path.join(dir, entry.name);
|
||||||
if (entry.isDirectory()) {
|
if (entry.isDirectory()) {
|
||||||
results = results.concat(getAllCommandFiles(fullPath));
|
results = results.concat(getAllCommandFiles(fullPath));
|
||||||
} else if (entry.isFile() && entry.name.endsWith('.js')) {
|
} else if (entry.isFile() && entry.name.endsWith('.js')) {
|
||||||
results.push(path.relative(commandsPath, fullPath));
|
results.push(path.relative(commandsPath, fullPath));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
const commandFiles = getAllCommandFiles(commandsPath);
|
const commandFiles = getAllCommandFiles(commandsPath);
|
||||||
|
|
||||||
let loaded = 0;
|
let loaded = 0;
|
||||||
|
|
||||||
for (const file of commandFiles) {
|
for (const file of commandFiles) {
|
||||||
try {
|
try {
|
||||||
const command = require(path.join(commandsPath, file));
|
const command = require(path.join(commandsPath, file));
|
||||||
|
|
||||||
if (!command.name || typeof command.execute !== 'function') {
|
if (!command.name || typeof command.execute !== 'function') {
|
||||||
logger.warn(
|
logger.warn(
|
||||||
`[commandhandler] skipping ${file}: missing "name" or "execute"`,
|
`[commandhandler] skipping ${file}: missing "name" or "execute"`,
|
||||||
);
|
);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
client.commands.set(command.name.toLowerCase(), command);
|
client.commands.set(command.name.toLowerCase(), command);
|
||||||
|
|
||||||
// Register aliases if provided
|
// Register aliases if provided
|
||||||
if (Array.isArray(command.aliases)) {
|
if (Array.isArray(command.aliases)) {
|
||||||
for (const alias of command.aliases) {
|
for (const alias of command.aliases) {
|
||||||
client.commands.set(alias.toLowerCase(), command);
|
client.commands.set(alias.toLowerCase(), command);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.debug(`[commandhandler] loaded command: ${command.name}`);
|
logger.debug(`[commandhandler] loaded command: ${command.name}`);
|
||||||
loaded++;
|
loaded++;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error(`[commandhandler] failed to load ${file}:`, err);
|
logger.error(`[commandhandler] failed to load ${file}:`, err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info(`[commandhandler] ${loaded} command(s) loaded`);
|
logger.info(`[commandhandler] ${loaded} command(s) loaded`);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = { loadCommands };
|
module.exports = { loadCommands };
|
||||||
@@ -1,53 +1,53 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const { Events } = require('discord.js');
|
const { Events } = require('discord.js');
|
||||||
const guildMemberAddEvent = require('../events/guildMemberAdd');
|
const guildMemberAddEvent = require('../events/guildMemberAdd');
|
||||||
const logger = require('../utils/logger');
|
const logger = require('../utils/logger');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads all event files from src/events and registers them on the client.
|
* Loads all event files from src/events and registers them on the client.
|
||||||
* Each event file must export: { name, once?, execute }
|
* Each event file must export: { name, once?, execute }
|
||||||
*
|
*
|
||||||
* @param {import('discord.js').Client} client
|
* @param {import('discord.js').Client} client
|
||||||
*/
|
*/
|
||||||
function loadEvents(client) {
|
function loadEvents(client) {
|
||||||
const eventsPath = path.join(__dirname, '..', 'events');
|
const eventsPath = path.join(__dirname, '..', 'events');
|
||||||
const eventFiles = fs
|
const eventFiles = fs
|
||||||
.readdirSync(eventsPath)
|
.readdirSync(eventsPath)
|
||||||
.filter((file) => file.endsWith('.js'));
|
.filter((file) => file.endsWith('.js'));
|
||||||
|
|
||||||
let loaded = 0;
|
let loaded = 0;
|
||||||
|
|
||||||
for (const file of eventFiles) {
|
for (const file of eventFiles) {
|
||||||
try {
|
try {
|
||||||
const event = require(path.join(eventsPath, file));
|
const event = require(path.join(eventsPath, file));
|
||||||
|
|
||||||
if (!event.name || typeof event.execute !== 'function') {
|
if (!event.name || typeof event.execute !== 'function') {
|
||||||
logger.warn(
|
logger.warn(
|
||||||
`[eventhandler] skipping ${file}: missing "name" or "execute"`,
|
`[eventhandler] skipping ${file}: missing "name" or "execute"`,
|
||||||
);
|
);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.once) {
|
if (event.once) {
|
||||||
client.once(event.name, (...args) => event.execute(client, ...args));
|
client.once(event.name, (...args) => event.execute(client, ...args));
|
||||||
} else {
|
} else {
|
||||||
client.on(event.name, (...args) => event.execute(client, ...args));
|
client.on(event.name, (...args) => event.execute(client, ...args));
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.debug(`[eventhandler] registered event: ${event.name}`);
|
logger.debug(`[eventhandler] registered event: ${event.name}`);
|
||||||
loaded++;
|
loaded++;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error(`[eventhandler] failed to load ${file}:`, err);
|
logger.error(`[eventhandler] failed to load ${file}:`, err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
client.on(Events.GuildMemberAdd, guildMemberAddEvent.bind(null, client));
|
client.on(Events.GuildMemberAdd, guildMemberAddEvent.bind(null, client));
|
||||||
loaded++;
|
loaded++;
|
||||||
|
|
||||||
logger.info(`[eventhandler] ${loaded} event(s) registered`);
|
logger.info(`[eventhandler] ${loaded} event(s) registered`);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = { loadEvents };
|
module.exports = { loadEvents };
|
||||||
+50
-50
@@ -1,50 +1,50 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
require('dotenv').config();
|
require('dotenv').config();
|
||||||
|
|
||||||
const { Client, Collection, GatewayIntentBits } = require('discord.js');
|
const { Client, Collection, GatewayIntentBits } = require('discord.js');
|
||||||
const logger = require('./utils/logger');
|
const logger = require('./utils/logger');
|
||||||
const { loadCommands } = require('./handlers/commandHandler');
|
const { loadCommands } = require('./handlers/commandHandler');
|
||||||
const { loadEvents } = require('./handlers/eventHandler');
|
const { loadEvents } = require('./handlers/eventHandler');
|
||||||
|
|
||||||
// Validate required environment variables
|
// Validate required environment variables
|
||||||
if (!process.env.BOT_TOKEN) {
|
if (!process.env.BOT_TOKEN) {
|
||||||
logger.error(
|
logger.error(
|
||||||
'BOT_TOKEN is not set. Copy .env.example to .env and fill in your token.',
|
'BOT_TOKEN is not set. Copy .env.example to .env and fill in your token.',
|
||||||
);
|
);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the Discord client with the intents needed for prefix commands
|
// Create the Discord client with the intents needed for prefix commands
|
||||||
const client = new Client({
|
const client = new Client({
|
||||||
intents: [
|
intents: [
|
||||||
GatewayIntentBits.Guilds,
|
GatewayIntentBits.Guilds,
|
||||||
GatewayIntentBits.GuildMembers,
|
GatewayIntentBits.GuildMembers,
|
||||||
GatewayIntentBits.GuildMessages,
|
GatewayIntentBits.GuildMessages,
|
||||||
GatewayIntentBits.MessageContent, // Required to read message content for prefix commands
|
GatewayIntentBits.MessageContent, // Required to read message content for prefix commands
|
||||||
GatewayIntentBits.DirectMessages,
|
GatewayIntentBits.DirectMessages,
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
// Attach a Collection to store commands
|
// Attach a Collection to store commands
|
||||||
client.commands = new Collection();
|
client.commands = new Collection();
|
||||||
|
|
||||||
// Load commands and events
|
// Load commands and events
|
||||||
loadCommands(client);
|
loadCommands(client);
|
||||||
loadEvents(client);
|
loadEvents(client);
|
||||||
|
|
||||||
// Global error handling
|
// Global error handling
|
||||||
process.on('unhandledRejection', (err) => {
|
process.on('unhandledRejection', (err) => {
|
||||||
logger.error('[process] unhandled rejection:', err);
|
logger.error('[process] unhandled rejection:', err);
|
||||||
});
|
});
|
||||||
|
|
||||||
process.on('uncaughtException', (err) => {
|
process.on('uncaughtException', (err) => {
|
||||||
logger.error('[process] uncaught exception:', err);
|
logger.error('[process] uncaught exception:', err);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Connect to Discord
|
// Connect to Discord
|
||||||
client.login(process.env.BOT_TOKEN).catch((err) => {
|
client.login(process.env.BOT_TOKEN).catch((err) => {
|
||||||
logger.error('[login] failed to log in:', err);
|
logger.error('[login] failed to log in:', err);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
});
|
});
|
||||||
+74
-74
@@ -1,74 +1,74 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const { createLogger, format, transports } = require('winston');
|
const { createLogger, format, transports } = require('winston');
|
||||||
const { consoleFormat } = require("winston-console-format");
|
const { consoleFormat } = require("winston-console-format");
|
||||||
const { printf } = format;
|
const { printf } = format;
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
|
||||||
const logs_dir = path.join(__dirname, '..', '..', 'logs');
|
const logs_dir = path.join(__dirname, '..', '..', 'logs');
|
||||||
if (!fs.existsSync(logs_dir)) {
|
if (!fs.existsSync(logs_dir)) {
|
||||||
fs.mkdirSync(logs_dir, { recursive: true });
|
fs.mkdirSync(logs_dir, { recursive: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
const logger = createLogger({
|
const logger = createLogger({
|
||||||
level: "silly",
|
level: "silly",
|
||||||
format: format.combine(
|
format: format.combine(
|
||||||
format.timestamp(),
|
format.timestamp(),
|
||||||
format.ms(),
|
format.ms(),
|
||||||
format.errors({ stack: true }),
|
format.errors({ stack: true }),
|
||||||
format.splat(),
|
format.splat(),
|
||||||
format.json({ space: 2 })
|
format.json({ space: 2 })
|
||||||
),
|
),
|
||||||
transports: [
|
transports: [
|
||||||
new transports.Console({
|
new transports.Console({
|
||||||
format: format.combine(
|
format: format.combine(
|
||||||
format.colorize({ all: true }),
|
format.colorize({ all: true }),
|
||||||
format.padLevels(),
|
format.padLevels(),
|
||||||
consoleFormat({
|
consoleFormat({
|
||||||
showMeta: true,
|
showMeta: true,
|
||||||
metaStrip: ["timestamp", "service"],
|
metaStrip: ["timestamp", "service"],
|
||||||
inspectOptions: {
|
inspectOptions: {
|
||||||
depth: Infinity,
|
depth: Infinity,
|
||||||
colors: true,
|
colors: true,
|
||||||
maxArrayLength: Infinity,
|
maxArrayLength: Infinity,
|
||||||
breakLength: 120,
|
breakLength: 120,
|
||||||
compact: Infinity,
|
compact: Infinity,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
}),
|
}),
|
||||||
|
|
||||||
new transports.File({
|
new transports.File({
|
||||||
filename: path.join(logs_dir, 'combined.log'),
|
filename: path.join(logs_dir, 'combined.log'),
|
||||||
format: format.combine(
|
format: format.combine(
|
||||||
format.timestamp(),
|
format.timestamp(),
|
||||||
format.ms(),
|
format.ms(),
|
||||||
format.errors({ stack: true }),
|
format.errors({ stack: true }),
|
||||||
format.splat(),
|
format.splat(),
|
||||||
format.json({ space: 2 })
|
format.json({ space: 2 })
|
||||||
),
|
),
|
||||||
}),
|
}),
|
||||||
|
|
||||||
new transports.File({
|
new transports.File({
|
||||||
filename: path.join(logs_dir, 'error.log'),
|
filename: path.join(logs_dir, 'error.log'),
|
||||||
level: 'error',
|
level: 'error',
|
||||||
format: format.combine(
|
format: format.combine(
|
||||||
format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss.SSS' }),
|
format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss.SSS' }),
|
||||||
format.errors({ stack: true }),
|
format.errors({ stack: true }),
|
||||||
printf(({ level, message, timestamp, stack, ...meta }) => {
|
printf(({ level, message, timestamp, stack, ...meta }) => {
|
||||||
let log = `${timestamp} [${level.toUpperCase()}]: ${message}`;
|
let log = `${timestamp} [${level.toUpperCase()}]: ${message}`;
|
||||||
if (stack) {
|
if (stack) {
|
||||||
log += `\ntrace: ${stack}`;
|
log += `\ntrace: ${stack}`;
|
||||||
}
|
}
|
||||||
if (Object.keys(meta).length > 0) {
|
if (Object.keys(meta).length > 0) {
|
||||||
log += `\nmetadata: ${JSON.stringify(meta, null, 2)}`;
|
log += `\nmetadata: ${JSON.stringify(meta, null, 2)}`;
|
||||||
}
|
}
|
||||||
return log;
|
return log;
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = logger;
|
module.exports = logger;
|
||||||
Reference in new issue
Block a user