Compare commits
4 commits
81d95ef102
...
136bc0805e
Author | SHA1 | Date | |
---|---|---|---|
136bc0805e | |||
ff9f3e458e | |||
097b7284e6 | |||
fef80709ee |
6 changed files with 256 additions and 11 deletions
60
README.md
60
README.md
|
@ -1,2 +1,60 @@
|
|||
# card-drop
|
||||
# Card Drop
|
||||
|
||||
Card Drop is a Discord Bot designed to allow users to "drop" random cards into
|
||||
a channel and have the ability to claim them for themselves or let others if
|
||||
they so choose.
|
||||
|
||||
The cards are randomly chosen based on weights of their card type (i.e. Bronze
|
||||
is more common than Gold). The user who ran the drop command has 5 minutes to
|
||||
choose if they want the card to themselves before its claimable by anyone, or
|
||||
until the drop command is ran again.
|
||||
|
||||
## Installation
|
||||
|
||||
Downloads of the latest version can be found from the [GitHub Releases](https://github.com/vylpes/card-drop/releases)
|
||||
or [Forgejo Releases](https://git.vylpes.xyz/external/card-drop/releases) page.
|
||||
|
||||
Copy the config template file and fill in the strings.
|
||||
|
||||
## Requirements
|
||||
|
||||
- NodeJS
|
||||
- Yarn
|
||||
- Docker
|
||||
|
||||
## Usage
|
||||
|
||||
Install the dependencies and build the app:
|
||||
|
||||
```bash
|
||||
yarn Install
|
||||
yarn build
|
||||
```
|
||||
|
||||
Setup the database (Recommended to use the docker-compose file
|
||||
|
||||
```bash
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
Copy and edit the settings file
|
||||
|
||||
```bash
|
||||
cp .env.template .env
|
||||
```
|
||||
|
||||
> **NOTE:** Make sure you do *not* check in these files! These contain
|
||||
sensitive information and should be treated as private.
|
||||
|
||||
If you're not using `DB_SYNC=true` in `.env`, make sure to migrate the database
|
||||
|
||||
```bash
|
||||
yarn db:up
|
||||
```
|
||||
|
||||
Start the bot
|
||||
|
||||
```bash
|
||||
yarn start
|
||||
```
|
||||
|
||||
|
|
120
docs/cards.md
Normal file
120
docs/cards.md
Normal file
|
@ -0,0 +1,120 @@
|
|||
# Cards
|
||||
|
||||
This document will describe how to add cards to the bot. This is from the
|
||||
perspective of the development side and doesn't go into details of syncing
|
||||
from an external place such as with the Google Drive Sync function.
|
||||
|
||||
The cards will be put into the `$DATA_DIR/cards` folder. `$DATA_DIR` is
|
||||
configured in the `.env` file.
|
||||
|
||||
## Folder Structure
|
||||
|
||||
The general structure of the cards folder is as follows:
|
||||
|
||||
```
|
||||
cards # The main cards folder
|
||||
| Series 1 # Series folder
|
||||
| | BRONZE # Type folder
|
||||
| | | 1000.jpg # Card image
|
||||
| | | 1001.jpg
|
||||
| | 1.json # Card metadata file
|
||||
| Series 2
|
||||
| | SILVER
|
||||
| | | 2000.jpg
|
||||
| | 2.json
|
||||
```
|
||||
|
||||
- The root of the cards folder will have a folder foor each series
|
||||
- Each series will contain folders for each of the card types containing the
|
||||
card images.
|
||||
- The series folder will also contain a metadata JSON folder containing the
|
||||
metadata of the cards within that series.
|
||||
|
||||
The bot when loading will search the cards folder recursively for each json,
|
||||
and then read them to determine what cards should be used for the bot.
|
||||
|
||||
## Series Metadata
|
||||
|
||||
An example of what the metadata files could look like are as follows:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Series 1",
|
||||
"cards": [
|
||||
{
|
||||
"id": "1000",
|
||||
"name": "Card 1000 of Series 1",
|
||||
"type": 1,
|
||||
"path": "Series 1/BRONZE/1000.jpg"
|
||||
},
|
||||
{
|
||||
"id": "1001",
|
||||
"name": "Card 1001 of Series 1",
|
||||
"type": 1,
|
||||
"path": "Series 2/BRONZE?1001.jpg",
|
||||
"subseries": "Custom Series Name"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
This file will load a series called "Series 1" with the id of 1, containing 2
|
||||
cards:
|
||||
- Card 1000, with type 1 (Bronze), with its image located at (from root)
|
||||
"Series 1/BRONZE/1000.jpg"
|
||||
- Card 1001 is the same, except has a custom "subseries" name which will
|
||||
override the main series name if shown, helpful for an "other" category.
|
||||
|
||||
### Card Type
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Number</th>
|
||||
<th>Name</th>
|
||||
<th>Chance</th>
|
||||
<th>Sacrifice Cost (Coins)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>0</td>
|
||||
<td>Unknown</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>1</td>
|
||||
<td>Bronze</td>
|
||||
<td>62%</td>
|
||||
<td>5</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>2</td>
|
||||
<td>Silver</td>
|
||||
<td>31%</td>
|
||||
<td>10</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>3</td>
|
||||
<td>Gold</td>
|
||||
<td>4.4%</td>
|
||||
<td>30</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>4</td>
|
||||
<td>Manga</td>
|
||||
<td>2%</td>
|
||||
<td>40</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>5</td>
|
||||
<td>Legendary</td>
|
||||
<td>0.6%</td>
|
||||
<td>100</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
10
package.json
10
package.json
|
@ -7,7 +7,7 @@
|
|||
"clean": "rm -rf node_modules/ dist/",
|
||||
"build": "tsc",
|
||||
"start": "node ./dist/bot.js",
|
||||
"test": "jest --passWithNoTests",
|
||||
"test": "jest",
|
||||
"lint": "eslint .",
|
||||
"lint:fix": "eslint . --fix",
|
||||
"db:up": "typeorm migration:run -d dist/database/dataSources/appDataSource.js",
|
||||
|
@ -15,11 +15,11 @@
|
|||
"db:create": "typeorm migration:create ./src/database/migrations/app/new",
|
||||
"release": "np --no-publish"
|
||||
},
|
||||
"repository": "https://gitea.vylpes.xyz/External/card-drop.git",
|
||||
"repository": "https://git.vylpes.xyz/External/card-drop.git",
|
||||
"author": "Ethan Lane <ethan@vylpes.com>",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https//gitea.vylpes.xyz/External/card-drop/issues",
|
||||
"url": "https//git.vylpes.xyz/External/card-drop/issues",
|
||||
"email": "helpdesk@vylpes.com"
|
||||
},
|
||||
"homepage": "https://gitea.vylpes.xyz/External/card-drop",
|
||||
|
@ -49,8 +49,8 @@
|
|||
"winston-daily-rotate-file": "^5.0.0",
|
||||
"winston-discord-transport": "^1.3.0"
|
||||
},
|
||||
"overrides": {
|
||||
"undici": "^5.28.3"
|
||||
"resolutions": {
|
||||
"**/ws": "^8.17.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.0.0",
|
||||
|
|
|
@ -16,7 +16,8 @@ export default class AllBalance extends Command {
|
|||
public override async execute(interaction: CommandInteraction) {
|
||||
const users = await User.FetchAll(User);
|
||||
|
||||
const filteredUsers = users.filter(x => x.Currency > 0);
|
||||
const filteredUsers = users.filter(x => x.Currency > 0)
|
||||
.sort((a, b) => b.Currency - a.Currency);
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setColor(EmbedColours.Ok)
|
||||
|
|
66
tests/registry.test.ts
Normal file
66
tests/registry.test.ts
Normal file
|
@ -0,0 +1,66 @@
|
|||
import {CoreClient} from "../src/client/client";
|
||||
import Registry from "../src/registry";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
|
||||
describe("RegisterCommands", () => {
|
||||
test("EXPECT every command in the commands folder to be registered", () => {
|
||||
const registeredCommands: string[] = [];
|
||||
|
||||
CoreClient.RegisterCommand = jest.fn().mockImplementation((name: string) => {
|
||||
registeredCommands.push(name);
|
||||
});
|
||||
|
||||
Registry.RegisterCommands();
|
||||
|
||||
const commandFiles = getFilesInDirectory(path.join(process.cwd(), "src", "commands"))
|
||||
.filter(x => x.endsWith(".ts"));
|
||||
|
||||
for (const file of commandFiles) {
|
||||
expect(registeredCommands).toContain(file.split("/").pop()!.split(".")[0]);
|
||||
}
|
||||
|
||||
expect(commandFiles.length).toBe(registeredCommands.length);
|
||||
});
|
||||
});
|
||||
|
||||
describe("RegisterButtonEvents", () => {
|
||||
test("EXEPCT every button event in the button events folder to be registered", () => {
|
||||
const registeredButtonEvents: string[] = [];
|
||||
|
||||
CoreClient.RegisterButtonEvent = jest.fn().mockImplementation((name: string) => {
|
||||
registeredButtonEvents.push(name);
|
||||
});
|
||||
|
||||
Registry.RegisterButtonEvents();
|
||||
|
||||
const eventFiles = getFilesInDirectory(path.join(process.cwd(), "src", "buttonEvents"))
|
||||
.filter(x => x.endsWith(".ts"));
|
||||
|
||||
for (const file of eventFiles) {
|
||||
expect(registeredButtonEvents).toContain(file.split("/").pop()!.split(".")[0].toLowerCase());
|
||||
}
|
||||
|
||||
expect(eventFiles.length).toBe(registeredButtonEvents.length);
|
||||
});
|
||||
});
|
||||
|
||||
function getFilesInDirectory(dir: string): string[] {
|
||||
let results: string[] = [];
|
||||
const list = fs.readdirSync(dir);
|
||||
|
||||
list.forEach(file => {
|
||||
file = path.join(dir, file);
|
||||
const stat = fs.statSync(file);
|
||||
|
||||
if (stat && stat.isDirectory()) {
|
||||
/* recurse into a subdirectory */
|
||||
results = results.concat(getFilesInDirectory(file));
|
||||
} else {
|
||||
/* is a file */
|
||||
results.push(file);
|
||||
}
|
||||
});
|
||||
|
||||
return results;
|
||||
}
|
|
@ -6838,10 +6838,10 @@ write-file-atomic@^4.0.2:
|
|||
imurmurhash "^0.1.4"
|
||||
signal-exit "^3.0.7"
|
||||
|
||||
ws@^8.16.0:
|
||||
version "8.17.0"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.0.tgz#d145d18eca2ed25aaf791a183903f7be5e295fea"
|
||||
integrity sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==
|
||||
ws@^8.16.0, ws@^8.17.1:
|
||||
version "8.18.0"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc"
|
||||
integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==
|
||||
|
||||
xdg-basedir@^5.0.1, xdg-basedir@^5.1.0:
|
||||
version "5.1.0"
|
||||
|
|
Loading…
Reference in a new issue