Compare commits

..

24 commits

Author SHA1 Message Date
cfcc8ad100 0.6.0
All checks were successful
Deploy To Production / build (push) Successful in 2m30s
Deploy To Production / deploy (push) Successful in 17s
Deploy To Stage / build (push) Successful in 11s
Deploy To Stage / deploy (push) Successful in 16s
2024-06-01 18:09:42 +01:00
302a762912 0.6.0 2024-06-01 18:07:04 +01:00
6b9d71758a Add a warning to the logs if an ID is used twice (#248)
All checks were successful
Deploy To Stage / build (push) Successful in 10s
Deploy To Stage / deploy (push) Successful in 16s
# Description

Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change.

- Make the bot log a warning if the card metadata function finds duplicated ids

#233

## Type of change

Please delete options that are not relevant.

- [x] New feature (non-breaking change which adds functionality)

# How Has This Been Tested?

Please describe the tests that you ran to verify the changes. Provide instructions so we can reproduce. Please also list any relevant details to your test configuration.

# Checklist

- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that provde my fix is effective or that my feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream modules

Reviewed-on: #248
Reviewed-by: VylpesTester <tester@vylpes.com>
Co-authored-by: Ethan Lane <ethan@vylpes.com>
Co-committed-by: Ethan Lane <ethan@vylpes.com>
2024-06-01 14:52:38 +01:00
682f62d42b Update the daily command text to be more user friendly (#246)
All checks were successful
Deploy To Stage / build (push) Successful in 2m30s
Deploy To Stage / deploy (push) Successful in 17s
# Description

Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change.

- Update the daily command text to be more user friendly

#202, #240

## Type of change

Please delete options that are not relevant.

- [x] New feature (non-breaking change which adds functionality)

# How Has This Been Tested?

Please describe the tests that you ran to verify the changes. Provide instructions so we can reproduce. Please also list any relevant details to your test configuration.

# Checklist

- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that provde my fix is effective or that my feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream modules

Reviewed-on: #246
Reviewed-by: VylpesTester <tester@vylpes.com>
Co-authored-by: Ethan Lane <ethan@vylpes.com>
Co-committed-by: Ethan Lane <ethan@vylpes.com>
2024-06-01 14:49:13 +01:00
916244b57c Add balance command (#244)
All checks were successful
Deploy To Stage / build (push) Successful in 10s
Deploy To Stage / deploy (push) Successful in 19s
# Description

Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change.

- Create balance command

#228

## Type of change

Please delete options that are not relevant.

- [x] New feature (non-breaking change which adds functionality)

# How Has This Been Tested?

Please describe the tests that you ran to verify the changes. Provide instructions so we can reproduce. Please also list any relevant details to your test configuration.

# Checklist

- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that provde my fix is effective or that my feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream modules

Reviewed-on: #244
Reviewed-by: VylpesTester <tester@vylpes.com>
Co-authored-by: Ethan Lane <ethan@vylpes.com>
Co-committed-by: Ethan Lane <ethan@vylpes.com>
2024-06-01 14:47:21 +01:00
696810e093 Update the give currency timer to give 10 coins every 20 minutes (#236)
All checks were successful
Deploy To Stage / build (push) Successful in 2m31s
Deploy To Stage / deploy (push) Successful in 17s
# Description

Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change.

- Give the currency to a user every 20 minutes
- This is enough so that they can run claim once every 20 minutes

#204, #226, #229

## Type of change

Please delete options that are not relevant.

- [x] Bug fix (non-breaking change which fixes an issue)

# How Has This Been Tested?

Please describe the tests that you ran to verify the changes. Provide instructions so we can reproduce. Please also list any relevant details to your test configuration.

# Checklist

- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that provde my fix is effective or that my feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream modules

Reviewed-on: #236
Reviewed-by: VylpesTester <tester@vylpes.com>
Co-authored-by: Ethan Lane <ethan@vylpes.com>
Co-committed-by: Ethan Lane <ethan@vylpes.com>
2024-06-01 14:42:51 +01:00
be2b837d56 Merge branch 'main' into develop
All checks were successful
Deploy To Stage / build (push) Successful in 22s
Deploy To Stage / deploy (push) Successful in 16s
2024-05-30 17:38:33 +01:00
e36ef85507 Merge branch 'hotfix/0.5.2' into develop
All checks were successful
Deploy To Stage / build (push) Successful in 11s
Deploy To Stage / deploy (push) Successful in 16s
2024-05-29 17:40:36 +01:00
318b07e206 Update dependency ts-jest to v29.1.3 (#241)
All checks were successful
Deploy To Stage / build (push) Successful in 2m29s
Deploy To Stage / deploy (push) Successful in 18s
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [ts-jest](https://kulshekhar.github.io/ts-jest) ([source](https://github.com/kulshekhar/ts-jest)) | dependencies | patch | [`29.1.2` -> `29.1.3`](https://renovatebot.com/diffs/npm/ts-jest/29.1.2/29.1.3) |

---

### Release Notes

<details>
<summary>kulshekhar/ts-jest (ts-jest)</summary>

### [`v29.1.3`](https://github.com/kulshekhar/ts-jest/blob/HEAD/CHANGELOG.md#2913-2024-05-21)

[Compare Source](https://github.com/kulshekhar/ts-jest/compare/v29.1.2...v29.1.3)

##### Bug Fixes

-   add `@jest/transform` as an optional peer dependency ([0ba7f86](0ba7f861c3))
-   bring back Node 14 support ([eda56a7](eda56a7797))

##### Performance Improvements

-   remove ts resolved module cache file ([4c88da5](4c88da5899))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4wLjAiLCJ1cGRhdGVkSW5WZXIiOiIzNy4wLjAiLCJ0YXJnZXRCcmFuY2giOiJkZXZlbG9wIn0=-->

Reviewed-on: #241
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-05-28 17:58:30 +01:00
aa1ee5588a Fix inventory showing quantities set to 0 (#239)
All checks were successful
Deploy To Stage / build (push) Successful in 11s
Deploy To Stage / deploy (push) Successful in 16s
# Description

Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change.

- Fix a bug where the inventory would show a "x0" quantity when there were entities in the database with a current quantity of 0.
- This occurs when you sacrifice cards, that command can't delete the row as it has claims connected to it in another table, so we need to maintain that key.

#227

## Type of change

Please delete options that are not relevant.

- [x] Bug fix (non-breaking change which fixes an issue)

# How Has This Been Tested?

Please describe the tests that you ran to verify the changes. Provide instructions so we can reproduce. Please also list any relevant details to your test configuration.

# Checklist

- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that provde my fix is effective or that my feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream modules

Co-authored-by: VylpesTester <tester@vylpes.com>
Reviewed-on: #239
Reviewed-by: VylpesTester <tester@vylpes.com>
Co-authored-by: Ethan Lane <ethan@vylpes.com>
Co-committed-by: Ethan Lane <ethan@vylpes.com>
2024-05-24 17:50:34 +01:00
5f513d740e Change sacrifice command embed colours to go green when successful from red (#237)
All checks were successful
Deploy To Stage / build (push) Successful in 2m30s
Deploy To Stage / deploy (push) Successful in 16s
# Description

Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change.

- Update the sacrifice command so that the embed starts red, goes grey if cancelled, and goes green if successful
- Fix event not checking if the user who ran the command is the same user who clicked the button
- Remove duplicated card name in the embed, didn't need it in the footer as well as the main body

#203, #230, #238

## Type of change

Please delete options that are not relevant.

- [x] New feature (non-breaking change which adds functionality)

# How Has This Been Tested?

Please describe the tests that you ran to verify the changes. Provide instructions so we can reproduce. Please also list any relevant details to your test configuration.

# Checklist

- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that provde my fix is effective or that my feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream modules

Co-authored-by: VylpesTester <tester@vylpes.com>
Reviewed-on: #237
Reviewed-by: VylpesTester <tester@vylpes.com>
Co-authored-by: Ethan Lane <ethan@vylpes.com>
Co-committed-by: Ethan Lane <ethan@vylpes.com>
2024-05-24 17:45:57 +01:00
17ea4d9ab4 Create daily command (#224)
All checks were successful
Deploy To Stage / build (push) Successful in 2m28s
Deploy To Stage / deploy (push) Successful in 17s
# Description

Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change.

- Create daily command, which gives 100 currency every day to a user who uses it
- Add constants class

#202

## Type of change

Please delete options that are not relevant.

- [x] New feature (non-breaking change which adds functionality)

# How Has This Been Tested?

Please describe the tests that you ran to verify the changes. Provide instructions so we can reproduce. Please also list any relevant details to your test configuration.

# Checklist

- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that provde my fix is effective or that my feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream modules

Reviewed-on: #224
Reviewed-by: VylpesTester <tester@vylpes.com>
Co-authored-by: Ethan Lane <ethan@vylpes.com>
Co-committed-by: Ethan Lane <ethan@vylpes.com>
2024-05-24 17:40:45 +01:00
caa991a259 Update dependency @discordjs/rest to v2.3.0 (#232)
All checks were successful
Deploy To Stage / build (push) Successful in 10s
Deploy To Stage / deploy (push) Successful in 17s
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [@discordjs/rest](https://discord.js.org) ([source](https://github.com/discordjs/discord.js)) | dependencies | minor | [`2.2.0` -> `2.3.0`](https://renovatebot.com/diffs/npm/@discordjs%2frest/2.2.0/2.3.0) |

---

### Release Notes

<details>
<summary>discordjs/discord.js (@&#8203;discordjs/rest)</summary>

### [`v2.3.0`](https://github.com/discordjs/discord.js/blob/HEAD/packages/rest/CHANGELOG.md#discordjsrest230---2024-05-04)

[Compare Source](https://github.com/discordjs/discord.js/compare/@discordjs/rest@2.2.0...@discordjs/rest@2.3.0)

#### Bug Fixes

-   Anchor link for events ([0efd1be](0efd1bea46))

#### Documentation

-   Split docs.api.json into multiple json files ([597340f](597340f288))
-   Remove hyphen after `@returns` ([#&#8203;9989](https://github.com/discordjs/discord.js/issues/9989)) ([e9ff991](e9ff99101b))

#### Features

-   Local and preview detection ([79fbda3](79fbda3aac))
-   **REST:** Dynamic rate limit offsets ([#&#8203;10099](https://github.com/discordjs/discord.js/issues/10099)) ([278396e](278396e815))

#### Refactor

-   Docs ([#&#8203;10126](https://github.com/discordjs/discord.js/issues/10126)) ([18cce83](18cce83d80))
-   Use interfaces for AsyncEventEmitter event maps ([#&#8203;10044](https://github.com/discordjs/discord.js/issues/10044)) ([adfd9cd](adfd9cd3b3))

#### Styling

-   Fix up lint ([d869d9b](d869d9b3fe))

#### Testing

-   Skip flaky rest test ([#&#8203;10234](https://github.com/discordjs/discord.js/issues/10234)) ([dc8f149](dc8f14967c))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4wLjAiLCJ1cGRhdGVkSW5WZXIiOiIzNy4wLjAiLCJ0YXJnZXRCcmFuY2giOiJkZXZlbG9wIn0=-->

Reviewed-on: #232
Reviewed-by: Vylpes <ethan@vylpes.com>
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-05-20 18:24:48 +01:00
40dbf8d2c0 Update dependency @types/node to v20.12.12 (#231)
All checks were successful
Deploy To Stage / build (push) Successful in 2m28s
Deploy To Stage / deploy (push) Successful in 16s
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node) ([source](https://github.com/DefinitelyTyped/DefinitelyTyped)) | devDependencies | patch | [`20.12.11` -> `20.12.12`](https://renovatebot.com/diffs/npm/@types%2fnode/20.12.11/20.12.12) |

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4wLjAiLCJ1cGRhdGVkSW5WZXIiOiIzNy4wLjAiLCJ0YXJnZXRCcmFuY2giOiJkZXZlbG9wIn0=-->

Reviewed-on: #231
Reviewed-by: Vylpes <ethan@vylpes.com>
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-05-20 18:21:33 +01:00
b8721c253c Create sacrifice command (#225)
All checks were successful
Deploy To Stage / build (push) Successful in 2m29s
Deploy To Stage / deploy (push) Successful in 15s
# Description

Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change.

- Create sacrifice command to be able to reclaim currency
- Add confirmation and cancel button events for the sacrifice command so people can confirm they want to do it

#203

## Type of change

Please delete options that are not relevant.

- [x] New feature (non-breaking change which adds functionality)

# How Has This Been Tested?

Please describe the tests that you ran to verify the changes. Provide instructions so we can reproduce. Please also list any relevant details to your test configuration.

# Checklist

- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that provde my fix is effective or that my feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream modules

Reviewed-on: #225
Reviewed-by: VylpesTester <tester@vylpes.com>
2024-05-17 21:02:52 +01:00
836a1d341f Add cron job to add coins to a user every 30 minutes (#219)
All checks were successful
Deploy To Stage / build (push) Successful in 2m30s
Deploy To Stage / deploy (push) Successful in 14s
# Description

Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change.

- Added a timer helper to run timers on a cron job
- Added a currency timer function to give a user 5 currency every 30 minutes

#204

## Type of change

Please delete options that are not relevant.

- [x] New feature (non-breaking change which adds functionality)

# How Has This Been Tested?

Please describe the tests that you ran to verify the changes. Provide instructions so we can reproduce. Please also list any relevant details to your test configuration.

# Checklist

- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that provde my fix is effective or that my feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream modules

Reviewed-on: #219
Reviewed-by: VylpesTester <tester@vylpes.com>
Co-authored-by: Ethan Lane <ethan@vylpes.com>
Co-committed-by: Ethan Lane <ethan@vylpes.com>
2024-05-17 20:57:01 +01:00
5a8ec932b4 Update dependency glob to v10.3.15 (#222)
All checks were successful
Deploy To Stage / build (push) Successful in 10s
Deploy To Stage / deploy (push) Successful in 16s
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [glob](https://github.com/isaacs/node-glob) | dependencies | patch | [`10.3.12` -> `10.3.15`](https://renovatebot.com/diffs/npm/glob/10.3.12/10.3.15) |

---

### Release Notes

<details>
<summary>isaacs/node-glob (glob)</summary>

### [`v10.3.15`](https://github.com/isaacs/node-glob/compare/v10.3.14...v10.3.15)

[Compare Source](https://github.com/isaacs/node-glob/compare/v10.3.14...v10.3.15)

### [`v10.3.14`](https://github.com/isaacs/node-glob/compare/v10.3.13...v10.3.14)

[Compare Source](https://github.com/isaacs/node-glob/compare/v10.3.13...v10.3.14)

### [`v10.3.13`](https://github.com/isaacs/node-glob/compare/v10.3.12...v10.3.13)

[Compare Source](https://github.com/isaacs/node-glob/compare/v10.3.12...v10.3.13)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4wLjAiLCJ1cGRhdGVkSW5WZXIiOiIzNy4wLjAiLCJ0YXJnZXRCcmFuY2giOiJkZXZlbG9wIn0=-->

Reviewed-on: #222
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-05-13 15:18:20 +01:00
b9264e23db Update dependency @types/node to v20.12.11 (#221)
All checks were successful
Deploy To Stage / build (push) Successful in 2m28s
Deploy To Stage / deploy (push) Successful in 14s
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node) ([source](https://github.com/DefinitelyTyped/DefinitelyTyped)) | devDependencies | patch | [`20.12.8` -> `20.12.11`](https://renovatebot.com/diffs/npm/@types%2fnode/20.12.8/20.12.11) |

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4wLjAiLCJ1cGRhdGVkSW5WZXIiOiIzNy4wLjAiLCJ0YXJnZXRCcmFuY2giOiJkZXZlbG9wIn0=-->

Reviewed-on: #221
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-05-13 15:15:21 +01:00
de14723df0 Update give command to allow currency to be given (#220)
All checks were successful
Deploy To Stage / build (push) Successful in 2m31s
Deploy To Stage / deploy (push) Successful in 14s
# Description

Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change.

- Update the give command to have the existing card functionality moved to a subcommand
- Add a subcommand to the give command to allow currency to be given

#206

## Type of change

Please delete options that are not relevant.

- [x] New feature (non-breaking change which adds functionality)

# How Has This Been Tested?

Please describe the tests that you ran to verify the changes. Provide instructions so we can reproduce. Please also list any relevant details to your test configuration.

# Checklist

- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that provde my fix is effective or that my feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream modules

Reviewed-on: #220
Reviewed-by: VylpesTester <tester@vylpes.com>
Co-authored-by: Ethan Lane <ethan@vylpes.com>
Co-committed-by: Ethan Lane <ethan@vylpes.com>
2024-05-11 12:48:48 +01:00
f07058d369 Update dependency jest-mock-extended to v3.0.7 (#218)
All checks were successful
Deploy To Stage / build (push) Successful in 11s
Deploy To Stage / deploy (push) Successful in 17s
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [jest-mock-extended](https://github.com/marchaos/jest-mock-extended) | dependencies | patch | [`3.0.6` -> `3.0.7`](https://renovatebot.com/diffs/npm/jest-mock-extended/3.0.6/3.0.7) |

---

### Release Notes

<details>
<summary>marchaos/jest-mock-extended (jest-mock-extended)</summary>

### [`v3.0.7`](https://github.com/marchaos/jest-mock-extended/releases/tag/3.0.7)

[Compare Source](77a64ae832...3.0.7)

Bumped ts-essentials

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4wLjAiLCJ1cGRhdGVkSW5WZXIiOiIzNy4wLjAiLCJ0YXJnZXRCcmFuY2giOiJkZXZlbG9wIn0=-->

Reviewed-on: #218
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-05-06 16:44:43 +01:00
f0870f0d61 Update dependency @types/node to v20.12.8 (#217)
All checks were successful
Deploy To Stage / build (push) Successful in 2m29s
Deploy To Stage / deploy (push) Successful in 15s
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node) ([source](https://github.com/DefinitelyTyped/DefinitelyTyped)) | devDependencies | patch | [`20.12.7` -> `20.12.8`](https://renovatebot.com/diffs/npm/@types%2fnode/20.12.7/20.12.8) |

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4wLjAiLCJ1cGRhdGVkSW5WZXIiOiIzNy4wLjAiLCJ0YXJnZXRCcmFuY2giOiJkZXZlbG9wIn0=-->

Reviewed-on: #217
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-05-06 16:41:08 +01:00
fca199d9bd Make claim button use currency to claim (#216)
All checks were successful
Deploy To Stage / build (push) Successful in 2m30s
Deploy To Stage / deploy (push) Successful in 14s
# Description

Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change.

#201

## Type of change

Please delete options that are not relevant.

- [x] New feature (non-breaking change which adds functionality)

# How Has This Been Tested?

Please describe the tests that you ran to verify the changes. Provide instructions so we can reproduce. Please also list any relevant details to your test configuration.

# Checklist

- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that provde my fix is effective or that my feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream modules

Reviewed-on: #216
Reviewed-by: VylpesTester <tester@vylpes.com>
Co-authored-by: Ethan Lane <ethan@vylpes.com>
Co-committed-by: Ethan Lane <ethan@vylpes.com>
2024-05-03 18:37:08 +01:00
dbbfd74c04 Update actions/setup-node action to v4 (#214)
All checks were successful
Deploy To Stage / build (push) Successful in 11s
Deploy To Stage / deploy (push) Successful in 16s
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [actions/setup-node](https://github.com/actions/setup-node) | action | major | `v1` -> `v4` |

---

### Release Notes

<details>
<summary>actions/setup-node (actions/setup-node)</summary>

### [`v4`](https://github.com/actions/setup-node/compare/v3...v4)

[Compare Source](https://github.com/actions/setup-node/compare/v3...v4)

### [`v3`](https://github.com/actions/setup-node/compare/v2...v3)

[Compare Source](https://github.com/actions/setup-node/compare/v2...v3)

### [`v2`](https://github.com/actions/setup-node/compare/v1...v2)

[Compare Source](https://github.com/actions/setup-node/compare/v1...v2)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4wLjAiLCJ1cGRhdGVkSW5WZXIiOiIzNy4wLjAiLCJ0YXJnZXRCcmFuY2giOiJkZXZlbG9wIn0=-->

Reviewed-on: #214
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-04-29 18:02:56 +01:00
6cff759135 Update actions/checkout action to v4 (#213)
All checks were successful
Deploy To Stage / build (push) Successful in 2m28s
Deploy To Stage / deploy (push) Successful in 14s
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [actions/checkout](https://github.com/actions/checkout) | action | major | `v2` -> `v4` |

---

### Release Notes

<details>
<summary>actions/checkout (actions/checkout)</summary>

### [`v4`](https://github.com/actions/checkout/blob/HEAD/CHANGELOG.md#v414)

[Compare Source](https://github.com/actions/checkout/compare/v3...v4)

-   Disable `extensions.worktreeConfig` when disabling `sparse-checkout` by [@&#8203;jww3](https://github.com/jww3) in https://github.com/actions/checkout/pull/1692
-   Add dependabot config by [@&#8203;cory-miller](https://github.com/cory-miller) in https://github.com/actions/checkout/pull/1688
-   Bump the minor-actions-dependencies group with 2 updates by [@&#8203;dependabot](https://github.com/dependabot) in https://github.com/actions/checkout/pull/1693
-   Bump word-wrap from 1.2.3 to 1.2.5 by [@&#8203;dependabot](https://github.com/dependabot) in https://github.com/actions/checkout/pull/1643

### [`v3`](https://github.com/actions/checkout/blob/HEAD/CHANGELOG.md#v360)

[Compare Source](https://github.com/actions/checkout/compare/v2...v3)

-   [Fix: Mark test scripts with Bash'isms to be run via Bash](https://github.com/actions/checkout/pull/1377)
-   [Add option to fetch tags even if fetch-depth > 0](https://github.com/actions/checkout/pull/579)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4wLjAiLCJ1cGRhdGVkSW5WZXIiOiIzNy4wLjAiLCJ0YXJnZXRCcmFuY2giOiJkZXZlbG9wIn0=-->

Reviewed-on: #213
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-04-29 17:59:25 +01:00
30 changed files with 706 additions and 84 deletions

View file

@ -7,29 +7,30 @@
# any secret values.
BOT_TOKEN=
BOT_VER=0.5.2
BOT_VER=0.6.0
BOT_AUTHOR=Vylpes
BOT_OWNERID=147392775707426816
BOT_CLIENTID=682942374040961060
BOT_ENV=4
BOT_ADMINS=147392775707426816,887272961504071690
BOT_LOGLEVEL=info
ABOUT_FUNDING=
ABOUT_REPO=
DATA_DIR=
DATA_DIR=./.temp
DB_HOST=
DB_PORT=
DB_NAME=
DB_HOST=127.0.0.1
DB_PORT=3301
DB_NAME=carddrop
DB_AUTH_USER=
DB_AUTH_PASS=
DB_SYNC=
DB_LOGGING=
DB_DATA_LOCATION=~/.docker
DB_DATA_LOCATION=./.temp/database
DB_CARD_FILE=:memory:
EXPRESS_PORT=3303
EXPRESS_PORT=3302
GDRIVESYNC_AUTO=true

View file

@ -12,9 +12,9 @@ jobs:
runs-on: node
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Use Node.js
uses: actions/setup-node@v1
uses: actions/setup-node@v4
with:
node-version: 18.x
- run: npm ci
@ -53,12 +53,13 @@ jobs:
DATA_DIR: ${{ secrets.PROD_DATA_DIR }}
GDRIVESYNC_AUTO: ${{ vars.PROD_GDRIVESYNC_AUTO }}
EXPRESS_PORT: ${{ secrets.PROD_EXPRESS_PORT }}
BOT_LOGLEVEL: ${{ vars.PROD_BOT_LOGLEVEL }}
with:
host: ${{ secrets.PROD_SSH_HOST }}
username: ${{ secrets.PROD_SSH_USER }}
key: ${{ secrets.PROD_SSH_KEY }}
port: ${{ secrets.PROD_SSH_PORT }}
envs: DB_NAME,DB_AUTH_USER,DB_AUTH_PASS,DB_HOST,DB_PORT,DB_ROOT_HOST,DB_SYNC,DB_LOGGING,DB_DATA_LOCATION,BOT_TOKEN,BOT_VER,BOT_AUTHOR,BOT_OWNERID,BOT_CLIENTID,ABOUT_FUNDING,ABOUT_REPO,BOT_ENV,BOT_ADMINS,DATA_DIR,GDRIVESYNC_AUTO,SERVER_PATH,EXPRESS_PORT
envs: DB_NAME,DB_AUTH_USER,DB_AUTH_PASS,DB_HOST,DB_PORT,DB_ROOT_HOST,DB_SYNC,DB_LOGGING,DB_DATA_LOCATION,BOT_TOKEN,BOT_VER,BOT_AUTHOR,BOT_OWNERID,BOT_CLIENTID,ABOUT_FUNDING,ABOUT_REPO,BOT_ENV,BOT_ADMINS,DATA_DIR,GDRIVESYNC_AUTO,SERVER_PATH,EXPRESS_PORT,BOT_LOGLEVEL
script: |
source .sshrc \
&& cd /home/vylpes/apps/card-drop/card-drop_prod \

View file

@ -12,9 +12,9 @@ jobs:
runs-on: node
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Use Node.js
uses: actions/setup-node@v1
uses: actions/setup-node@v4
with:
node-version: 18.x
- run: npm ci
@ -53,12 +53,13 @@ jobs:
DATA_DIR: ${{ secrets.STAGE_DATA_DIR }}
GDRIVESYNC_AUTO: ${{ vars.STAGE_GDRIVESYNC_AUTO }}
EXPRESS_PORT: ${{ secrets.STAGE_EXPRESS_PORT }}
BOT_LOGLEVEL: ${{ vars.STAGE_BOT_LOGLEVEL }}
with:
host: ${{ secrets.STAGE_SSH_HOST }}
username: ${{ secrets.STAGE_SSH_USER }}
key: ${{ secrets.STAGE_SSH_KEY }}
port: ${{ secrets.STAGE_SSH_PORT }}
envs: DB_NAME,DB_AUTH_USER,DB_AUTH_PASS,DB_HOST,DB_PORT,DB_ROOT_HOST,DB_SYNC,DB_LOGGING,DB_DATA_LOCATION,BOT_TOKEN,BOT_VER,BOT_AUTHOR,BOT_OWNERID,BOT_CLIENTID,ABOUT_FUNDING,ABOUT_REPO,BOT_ENV,BOT_ADMINS,DATA_DIR,GDRIVESYNC_AUTO,SERVER_PATH,EXPRESS_PORT
envs: DB_NAME,DB_AUTH_USER,DB_AUTH_PASS,DB_HOST,DB_PORT,DB_ROOT_HOST,DB_SYNC,DB_LOGGING,DB_DATA_LOCATION,BOT_TOKEN,BOT_VER,BOT_AUTHOR,BOT_OWNERID,BOT_CLIENTID,ABOUT_FUNDING,ABOUT_REPO,BOT_ENV,BOT_ADMINS,DATA_DIR,GDRIVESYNC_AUTO,SERVER_PATH,EXPRESS_PORT,BOT_LOGLEVEL
script: |
source .sshrc \
&& cd /home/vylpes/apps/card-drop/card-drop_stage \

View file

@ -14,9 +14,9 @@ jobs:
runs-on: node
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Use Node.js
uses: actions/setup-node@v1
uses: actions/setup-node@v4
with:
node-version: 18.x
- run: npm ci

2
.gitignore vendored
View file

@ -108,5 +108,5 @@ config.json
ormconfig.json
gdrive-credentials.json
data/
*.db
.temp/
*.db

View file

@ -0,0 +1,2 @@
ALTER TABLE `user`
ADD LastUsedDaily datetime null;

142
package-lock.json generated
View file

@ -1,12 +1,12 @@
{
"name": "card-drop",
"version": "0.5.2",
"version": "0.6.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "card-drop",
"version": "0.5.2",
"version": "0.6.0",
"license": "MIT",
"dependencies": {
"@discordjs/rest": "^2.0.0",
@ -16,6 +16,7 @@
"@types/uuid": "^9.0.0",
"body-parser": "^1.20.2",
"clone-deep": "^4.0.1",
"cron": "^3.1.7",
"discord.js": "^14.3.0",
"dotenv": "^16.0.0",
"express": "^4.18.2",
@ -747,10 +748,15 @@
}
},
"node_modules/@discordjs/collection": {
"version": "2.0.0",
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-2.1.0.tgz",
"integrity": "sha512-mLcTACtXUuVgutoznkh6hS3UFqYirDYAg5Dc1m8xn6OvPjetnUlf/xjtqnnc47OwWdaoCQnHmHh9KofhD6uRqw==",
"license": "Apache-2.0",
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/discordjs/discord.js?sponsor"
}
},
"node_modules/@discordjs/formatters": {
@ -764,28 +770,54 @@
}
},
"node_modules/@discordjs/rest": {
"version": "2.2.0",
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-2.3.0.tgz",
"integrity": "sha512-C1kAJK8aSYRv3ZwMG8cvrrW4GN0g5eMdP8AuN8ODH5DyOCbHgJspze1my3xHOAgwLJdKUbWNVyAeJ9cEdduqIg==",
"license": "Apache-2.0",
"dependencies": {
"@discordjs/collection": "^2.0.0",
"@discordjs/util": "^1.0.2",
"@sapphire/async-queue": "^1.5.0",
"@sapphire/snowflake": "^3.5.1",
"@vladfrangu/async_event_emitter": "^2.2.2",
"discord-api-types": "0.37.61",
"magic-bytes.js": "^1.5.0",
"@discordjs/collection": "^2.1.0",
"@discordjs/util": "^1.1.0",
"@sapphire/async-queue": "^1.5.2",
"@sapphire/snowflake": "^3.5.3",
"@vladfrangu/async_event_emitter": "^2.2.4",
"discord-api-types": "0.37.83",
"magic-bytes.js": "^1.10.0",
"tslib": "^2.6.2",
"undici": "5.27.2"
"undici": "6.13.0"
},
"engines": {
"node": ">=16.11.0"
},
"funding": {
"url": "https://github.com/discordjs/discord.js?sponsor"
}
},
"node_modules/@discordjs/rest/node_modules/@sapphire/snowflake": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.5.3.tgz",
"integrity": "sha512-jjmJywLAFoWeBi1W7994zZyiNWPIiqRRNAmSERxyg93xRGzNYvGjlZ0gR6x0F4gPRi2+0O6S71kOZYyr3cxaIQ==",
"license": "MIT",
"engines": {
"node": ">=v14.0.0",
"npm": ">=7.0.0"
}
},
"node_modules/@discordjs/rest/node_modules/discord-api-types": {
"version": "0.37.83",
"resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.83.tgz",
"integrity": "sha512-urGGYeWtWNYMKnYlZnOnDHm8fVRffQs3U0SpE8RHeiuLKb/u92APS8HoQnPTFbnXmY1vVnXjXO4dOxcAn3J+DA==",
"license": "MIT"
},
"node_modules/@discordjs/util": {
"version": "1.0.2",
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@discordjs/util/-/util-1.1.0.tgz",
"integrity": "sha512-IndcI5hzlNZ7GS96RV3Xw1R2kaDuXEp7tRIy/KlhidpN/BQ1qh1NZt3377dMLTa44xDUNKT7hnXkA/oUAzD/lg==",
"license": "Apache-2.0",
"engines": {
"node": ">=16.11.0"
},
"funding": {
"url": "https://github.com/discordjs/discord.js?sponsor"
}
},
"node_modules/@discordjs/ws": {
@ -1673,7 +1705,9 @@
}
},
"node_modules/@sapphire/async-queue": {
"version": "1.5.0",
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.5.2.tgz",
"integrity": "sha512-7X7FFAA4DngXUl95+hYbUF19bp1LGiffjJtu7ygrZrbdCSsdDDBaSjB7Akw0ZbOu6k0xpXyljnJ6/RZUvLfRdg==",
"license": "MIT",
"engines": {
"node": ">=v14.0.0",
@ -1895,14 +1929,20 @@
"@types/node": "*"
}
},
"node_modules/@types/luxon": {
"version": "3.4.2",
"resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.4.2.tgz",
"integrity": "sha512-TifLZlFudklWlMBfhubvgqTXRzLDI5pCbGa4P8a3wPyUQSW+1xQ5eDsreP9DWHX3tjq1ke96uYG/nwundroWcA=="
},
"node_modules/@types/mime": {
"version": "3.0.4",
"license": "MIT"
},
"node_modules/@types/node": {
"version": "20.12.7",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz",
"integrity": "sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==",
"version": "20.12.12",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.12.tgz",
"integrity": "sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==",
"license": "MIT",
"dependencies": {
"undici-types": "~5.26.4"
}
@ -3841,6 +3881,15 @@
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/cron": {
"version": "3.1.7",
"resolved": "https://registry.npmjs.org/cron/-/cron-3.1.7.tgz",
"integrity": "sha512-tlBg7ARsAMQLzgwqVxy8AZl/qlTc5nibqYwtNGoCrd+cV+ugI+tvZC1oT/8dFH8W455YrywGykx/KMmAqOr7Jw==",
"dependencies": {
"@types/luxon": "~3.4.0",
"luxon": "~3.4.0"
}
},
"node_modules/cross-spawn": {
"version": "7.0.3",
"license": "MIT",
@ -5154,21 +5203,21 @@
"license": "MIT"
},
"node_modules/glob": {
"version": "10.3.12",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz",
"integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==",
"version": "10.3.15",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.3.15.tgz",
"integrity": "sha512-0c6RlJt1TICLyvJYIApxb8GsXoai0KUP7AxKKAtsYXdgJR1mGEUa7DgwShbdk1nly0PYoZj01xd4hzbq3fsjpw==",
"dependencies": {
"foreground-child": "^3.1.0",
"jackspeak": "^2.3.6",
"minimatch": "^9.0.1",
"minipass": "^7.0.4",
"path-scurry": "^1.10.2"
"path-scurry": "^1.11.0"
},
"bin": {
"glob": "dist/esm/bin.mjs"
},
"engines": {
"node": ">=16 || 14 >=14.17"
"node": ">=16 || 14 >=14.18"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
@ -6816,11 +6865,11 @@
}
},
"node_modules/jest-mock-extended": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/jest-mock-extended/-/jest-mock-extended-3.0.6.tgz",
"integrity": "sha512-DJuEoFzio0loqdX8NIwkbE9dgIXNzaj//pefOQxGkoivohpxbSQeNHCAiXkDNA/fmM4EIJDoZnSibP4w3dUJ9g==",
"version": "3.0.7",
"resolved": "https://registry.npmjs.org/jest-mock-extended/-/jest-mock-extended-3.0.7.tgz",
"integrity": "sha512-7lsKdLFcW9B9l5NzZ66S/yTQ9k8rFtnwYdCNuRU/81fqDWicNDVhitTSPnrGmNeNm0xyw0JHexEOShrIKRCIRQ==",
"dependencies": {
"ts-essentials": "^9.4.2"
"ts-essentials": "^10.0.0"
},
"peerDependencies": {
"jest": "^24.0.0 || ^25.0.0 || ^26.0.0 || ^27.0.0 || ^28.0.0 || ^29.0.0",
@ -7700,8 +7749,18 @@
"node": ">=10"
}
},
"node_modules/luxon": {
"version": "3.4.4",
"resolved": "https://registry.npmjs.org/luxon/-/luxon-3.4.4.tgz",
"integrity": "sha512-zobTr7akeGHnv7eBOXcRgMeCP6+uyYsczwmeRCauvpvaAltgNyTbLH/+VaEAPUeWBT+1GuNmz4wC/6jtQzbbVA==",
"engines": {
"node": ">=12"
}
},
"node_modules/magic-bytes.js": {
"version": "1.6.0",
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/magic-bytes.js/-/magic-bytes.js-1.10.0.tgz",
"integrity": "sha512-/k20Lg2q8LE5xiaaSkMXk4sfvI+9EGEykFS4b0CHHGWqDYU0bGUFSwchNOMA56D7TCs9GwVTkqe9als1/ns8UQ==",
"license": "MIT"
},
"node_modules/make-dir": {
@ -9335,15 +9394,15 @@
"license": "MIT"
},
"node_modules/path-scurry": {
"version": "1.10.2",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz",
"integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==",
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
"integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
"dependencies": {
"lru-cache": "^10.2.0",
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
},
"engines": {
"node": ">=16 || 14 >=14.17"
"node": ">=16 || 14 >=14.18"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
@ -10847,11 +10906,11 @@
}
},
"node_modules/ts-essentials": {
"version": "9.4.2",
"resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-9.4.2.tgz",
"integrity": "sha512-mB/cDhOvD7pg3YCLk2rOtejHjjdSi9in/IBYE13S+8WA5FBSraYf4V/ws55uvs0IvQ/l0wBOlXy5yBNZ9Bl8ZQ==",
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-10.0.0.tgz",
"integrity": "sha512-77FHNJEyysF9+1s4G6eejuA1lxw7uMchT3ZPy3CIbh7GIunffpshtM8pTe5G6N5dpOzNevqRHew859ceLWVBfw==",
"peerDependencies": {
"typescript": ">=4.1.0"
"typescript": ">=4.5.0"
},
"peerDependenciesMeta": {
"typescript": {
@ -10860,9 +10919,10 @@
}
},
"node_modules/ts-jest": {
"version": "29.1.2",
"resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.2.tgz",
"integrity": "sha512-br6GJoH/WUX4pu7FbZXuWGKGNDuU7b8Uj77g/Sp7puZV6EXzuByl6JrECvm0MzVzSTkSHWTihsXt+5XYER5b+g==",
"version": "29.1.3",
"resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.3.tgz",
"integrity": "sha512-6L9qz3ginTd1NKhOxmkP0qU3FyKjj5CPoY+anszfVn6Pmv/RIKzhiMCsH7Yb7UvJR9I2A64rm4zQl531s2F1iw==",
"license": "MIT",
"dependencies": {
"bs-logger": "0.x",
"fast-json-stable-stringify": "2.x",
@ -10877,10 +10937,11 @@
"ts-jest": "cli.js"
},
"engines": {
"node": "^16.10.0 || ^18.0.0 || >=20.0.0"
"node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0"
},
"peerDependencies": {
"@babel/core": ">=7.0.0-beta.0 <8",
"@jest/transform": "^29.0.0",
"@jest/types": "^29.0.0",
"babel-jest": "^29.0.0",
"jest": "^29.0.0",
@ -10890,6 +10951,9 @@
"@babel/core": {
"optional": true
},
"@jest/transform": {
"optional": true
},
"@jest/types": {
"optional": true
},

View file

@ -1,6 +1,6 @@
{
"name": "card-drop",
"version": "0.5.2",
"version": "0.6.0",
"main": "./dist/bot.js",
"typings": "./dist",
"scripts": {
@ -32,6 +32,7 @@
"@types/uuid": "^9.0.0",
"body-parser": "^1.20.2",
"clone-deep": "^4.0.1",
"cron": "^3.1.7",
"discord.js": "^14.3.0",
"dotenv": "^16.0.0",
"express": "^4.18.2",

View file

@ -39,6 +39,13 @@ export default class CardMetadataFunction {
CoreClient.Cards = cardResult.Result!;
AppLogger.LogInfo("Functions/CardMetadataFunction", `Loaded ${CoreClient.Cards.flatMap(x => x.cards).length} cards to database`);
const duplicateCards = CoreClient.Cards.flatMap(x => x.cards)
.filter((card, index, self) => self.findIndex(c => c.id === card.id) !== index);
if (duplicateCards.length > 0) {
AppLogger.LogWarn("Functions/CardMetadataFunction", `Duplicate card ids found: ${duplicateCards.flatMap(x => x.id).join(", ")}`);
}
return {
IsSuccess: true,
};

View file

@ -37,7 +37,6 @@ const client = new CoreClient([
]);
Registry.RegisterCommands();
Registry.RegisterEvents();
Registry.RegisterButtonEvents();
if (!existsSync(`${process.env.DATA_DIR}/cards`) && process.env.GDRIVESYNC_AUTO && process.env.GDRIVESYNC_AUTO == "true") {

View file

@ -5,6 +5,8 @@ import { CoreClient } from "../client/client";
import { default as eClaim } from "../database/entities/app/Claim";
import AppLogger from "../client/appLogger";
import CardDropHelperMetadata from "../helpers/CardDropHelperMetadata";
import User from "../database/entities/app/User";
import CardConstants from "../constants/CardConstants";
export default class Claim extends ButtonEvent {
public override async execute(interaction: ButtonInteraction) {
@ -41,6 +43,17 @@ export default class Claim extends ButtonEvent {
await inventory.Save(Inventory, inventory);
const user = await User.FetchOneById(User, userId) || new User(userId, CardConstants.StartingCurrency);
AppLogger.LogSilly("Button/Claim", `${user.Id} has ${user.Currency} currency`);
if (!user.RemoveCurrency(CardConstants.ClaimCost)) {
await interaction.reply(`Not enough currency! You need 10 currency, you have ${user.Currency}`);
return;
}
await user.Save(User, user);
const claim = new eClaim(claimId);
claim.SetInventory(inventory);

View file

@ -0,0 +1,157 @@
import { ActionRowBuilder, ButtonBuilder, ButtonInteraction, ButtonStyle, EmbedBuilder } from "discord.js";
import { ButtonEvent } from "../type/buttonEvent";
import Inventory from "../database/entities/app/Inventory";
import CardDropHelperMetadata from "../helpers/CardDropHelperMetadata";
import { CardRarityToString, GetSacrificeAmount } from "../constants/CardRarity";
import EmbedColours from "../constants/EmbedColours";
import User from "../database/entities/app/User";
export default class Sacrifice extends ButtonEvent {
public override async execute(interaction: ButtonInteraction) {
const subcommand = interaction.customId.split(" ")[1];
switch(subcommand) {
case "confirm":
await this.confirm(interaction);
break;
case "cancel":
await this.cancel(interaction);
break;
}
}
private async confirm(interaction: ButtonInteraction) {
const userId = interaction.customId.split(" ")[2];
const cardNumber = interaction.customId.split(" ")[3];
if (userId != interaction.user.id) {
await interaction.reply("Only the user who created this sacrifice can confirm it.");
return;
}
const cardInInventory = await Inventory.FetchOneByCardNumberAndUserId(userId, cardNumber);
if (!cardInInventory) {
await interaction.reply("Unable to find card in inventory.");
return;
}
const cardData = CardDropHelperMetadata.GetCardByCardNumber(cardNumber);
if (!cardData) {
await interaction.reply("Unable to find card in the database.");
return;
}
const user = await User.FetchOneById(User, userId);
if (!user) {
await interaction.reply("Unable to find user in database.");
return;
}
cardInInventory.RemoveQuantity(1);
await cardInInventory.Save(Inventory, cardInInventory);
const cardValue = GetSacrificeAmount(cardData.card.type);
const cardRarityString = CardRarityToString(cardData.card.type);
user.AddCurrency(cardValue);
await user.Save(User, user);
const description = [
`Card: ${cardData.card.name}`,
`Series: ${cardData.series.name}`,
`Rarity: ${cardRarityString}`,
`Quantity Owned: ${cardInInventory.Quantity}`,
`Sacrifice Amount: ${cardValue}`,
];
const embed = new EmbedBuilder()
.setTitle("Card Sacrificed")
.setDescription(description.join("\n"))
.setColor(EmbedColours.Green)
.setFooter({ text: `${interaction.user.username}` });
const row = new ActionRowBuilder<ButtonBuilder>()
.addComponents([
new ButtonBuilder()
.setCustomId(`sacrifice confirm ${interaction.user.id} ${cardNumber}`)
.setLabel("Confirm")
.setStyle(ButtonStyle.Success)
.setDisabled(true),
new ButtonBuilder()
.setCustomId("sacrifice cancel")
.setLabel("Cancel")
.setStyle(ButtonStyle.Secondary)
.setDisabled(true),
]);
await interaction.update({
embeds: [ embed ],
components: [ row ],
});
}
private async cancel(interaction: ButtonInteraction) {
const userId = interaction.customId.split(" ")[2];
const cardNumber = interaction.customId.split(" ")[3];
if (userId != interaction.user.id) {
await interaction.reply("Only the user who created this sacrifice can cancel it.");
return;
}
const cardInInventory = await Inventory.FetchOneByCardNumberAndUserId(userId, cardNumber);
if (!cardInInventory) {
await interaction.reply("Unable to find card in inventory.");
return;
}
const cardData = CardDropHelperMetadata.GetCardByCardNumber(cardNumber);
if (!cardData) {
await interaction.reply("Unable to find card in the database.");
return;
}
const cardValue = GetSacrificeAmount(cardData.card.type);
const cardRarityString = CardRarityToString(cardData.card.type);
const description = [
`Card: ${cardData.card.name}`,
`Series: ${cardData.series.name}`,
`Rarity: ${cardRarityString}`,
`Quantity Owned: ${cardInInventory.Quantity}`,
`Sacrifice Amount: ${cardValue}`,
];
const embed = new EmbedBuilder()
.setTitle("Sacrifice Cancelled")
.setDescription(description.join("\n"))
.setColor(EmbedColours.Grey)
.setFooter({ text: `${interaction.user.username}` });
const row = new ActionRowBuilder<ButtonBuilder>()
.addComponents([
new ButtonBuilder()
.setCustomId(`sacrifice confirm ${interaction.user.id} ${cardNumber}`)
.setLabel("Confirm")
.setStyle(ButtonStyle.Success)
.setDisabled(true),
new ButtonBuilder()
.setCustomId("sacrifice cancel")
.setLabel("Cancel")
.setStyle(ButtonStyle.Secondary)
.setDisabled(true),
]);
await interaction.update({
embeds: [ embed ],
components: [ row ],
});
}
}

View file

@ -14,6 +14,8 @@ import Webhooks from "../webhooks";
import CardMetadataFunction from "../Functions/CardMetadataFunction";
import { SeriesMetadata } from "../contracts/SeriesMetadata";
import AppLogger from "./appLogger";
import TimerHelper from "../helpers/TimerHelper";
import GiveCurrency from "../timers/GiveCurrency";
export class CoreClient extends Client {
private static _commandItems: ICommandItem[];
@ -23,6 +25,7 @@ export class CoreClient extends Client {
private _events: Events;
private _util: Util;
private _webhooks: Webhooks;
private _timerHelper: TimerHelper;
public static ClaimId: string;
public static Environment: Environment;
@ -59,6 +62,7 @@ export class CoreClient extends Client {
this._events = new Events();
this._util = new Util();
this._webhooks = new Webhooks();
this._timerHelper = new TimerHelper();
AppLogger.LogInfo("Client", `Environment: ${CoreClient.Environment}`);
@ -72,7 +76,12 @@ export class CoreClient extends Client {
}
await AppDataSource.initialize()
.then(() => AppLogger.LogInfo("Client", "App Data Source Initialised"))
.then(() => {
AppLogger.LogInfo("Client", "App Data Source Initialised");
const timerId = this._timerHelper.AddTimer("*/20 * * * *", "Europe/London", GiveCurrency, false);
this._timerHelper.StartTimer(timerId);
})
.catch(err => {
AppLogger.LogError("Client", "App Data Source Initialisation Failed");
AppLogger.LogError("Client", err);

28
src/commands/balance.ts Normal file
View file

@ -0,0 +1,28 @@
import { CommandInteraction, EmbedBuilder, SlashCommandBuilder } from "discord.js";
import { Command } from "../type/command";
import User from "../database/entities/app/User";
import EmbedColours from "../constants/EmbedColours";
export default class Balance extends Command {
constructor() {
super();
this.CommandBuilder = new SlashCommandBuilder()
.setName("balance")
.setDescription("Get your currency balance");
}
public override async execute(interaction: CommandInteraction) {
const user = await User.FetchOneById(User, interaction.user.id);
let userBalance = user != null ? user.Currency : 0;
const embed = new EmbedBuilder()
.setColor(EmbedColours.Ok)
.setTitle("Balance")
.setDescription(`You currently have **${userBalance} currency**!`)
.setFooter({ text: interaction.user.username, iconURL: interaction.user.avatarURL() ?? undefined });
await interaction.reply({ embeds: [ embed ]});
}
}

43
src/commands/daily.ts Normal file
View file

@ -0,0 +1,43 @@
import { CommandInteraction, SlashCommandBuilder } from "discord.js";
import { Command } from "../type/command";
import User from "../database/entities/app/User";
import CardConstants from "../constants/CardConstants";
import TimeLengthInput from "../helpers/TimeLengthInput";
export default class Daily extends Command {
constructor() {
super();
this.CommandBuilder = new SlashCommandBuilder()
.setName("daily")
.setDescription("Gain bonus currency, once a day");
}
public override async execute(interaction: CommandInteraction) {
const user = await User.FetchOneById(User, interaction.user.id) ?? new User(interaction.user.id, CardConstants.StartingCurrency);
const dayAgo = new Date(Date.now() - (1000 * 60 * 60 * 24));
if (user.LastUsedDaily && user.LastUsedDaily > dayAgo) {
const timeNow = Date.now();
const timeLength = 24 * 60 * 60 * 1000; // 1 day
const timeLeft = Math.ceil(((timeLength - (timeNow - user.LastUsedDaily.getTime()))) / 1000 / 60);
const timeLeftHours = Math.floor(timeLeft / 60);
const timeLeftMinutes = timeLeft % 60;
const timeLeftString = new TimeLengthInput(`${timeLeftHours}h ${timeLeftMinutes}m`);
await interaction.reply(`You have already used the daily command! You can use it again in **${timeLeftString.GetLength()}**.`);
return;
}
user.AddCurrency(CardConstants.DailyCurrency);
user.UpdateLastUsedDaily(new Date());
await user.Save(User, user);
await interaction.reply(`Congratulations, you have claimed your daily ${CardConstants.DailyCurrency} currency! You now have ${user.Currency} currency and can claim again in 24 hours!`);
}
}

View file

@ -5,6 +5,7 @@ import Config from "../database/entities/app/Config";
import CardDropHelperMetadata from "../helpers/CardDropHelperMetadata";
import Inventory from "../database/entities/app/Inventory";
import AppLogger from "../client/appLogger";
import User from "../database/entities/app/User";
export default class Give extends Command {
constructor() {
@ -14,19 +15,57 @@ export default class Give extends Command {
.setName("give")
.setDescription("Give a user a card manually, in case bot breaks")
.setDefaultMemberPermissions(PermissionsBitField.Flags.Administrator)
.addStringOption(x =>
.addSubcommand(x =>
x
.setName("cardnumber")
.setDescription("G")
.setRequired(true))
.addUserOption(x =>
.setName("card")
.setDescription("Give a user a card manually")
.addStringOption(x =>
x
.setName("cardnumber")
.setDescription("The card to give")
.setRequired(true))
.addUserOption(x =>
x
.setName("user")
.setDescription("The user to give the card to")
.setRequired(true)))
.addSubcommand(x =>
x
.setName("user")
.setDescription("The user to give the card to")
.setRequired(true));
.setName("currency")
.setDescription("Give a user currency manually")
.addNumberOption(x =>
x
.setName("amount")
.setDescription("The amount to give")
.setRequired(true))
.addUserOption(x =>
x
.setName("user")
.setDescription("The user to give the currency to")
.setRequired(true)));
}
public override async execute(interaction: CommandInteraction<CacheType>) {
if (!interaction.isChatInputCommand()) return;
const whitelistedUsers = process.env.BOT_ADMINS!.split(",");
if (!whitelistedUsers.find(x => x == interaction.user.id)) {
await interaction.reply("Only whitelisted users can use this command.");
return;
}
switch (interaction.options.getSubcommand()) {
case "card":
await this.GiveCard(interaction);
break;
case "currency":
await this.GiveCurrency(interaction);
break;
}
}
private async GiveCard(interaction: CommandInteraction) {
if (!CoreClient.AllowDrops) {
await interaction.reply("Bot is currently syncing, please wait until its done.");
return;
@ -37,17 +76,10 @@ export default class Give extends Command {
return;
}
const whitelistedUsers = process.env.BOT_ADMINS!.split(",");
if (!whitelistedUsers.find(x => x == interaction.user.id)) {
await interaction.reply("Only whitelisted users can use this command.");
return;
}
const cardNumber = interaction.options.get("cardnumber", true);
const user = interaction.options.getUser("user", true);
AppLogger.LogSilly("Commands/Give", `Parameters: cardNumber=${cardNumber.value}, user=${user.id}`);
AppLogger.LogSilly("Commands/Give/GiveCard", `Parameters: cardNumber=${cardNumber.value}, user=${user.id}`);
const card = CardDropHelperMetadata.GetCardByCardNumber(cardNumber.value!.toString());
@ -66,6 +98,21 @@ export default class Give extends Command {
await inventory.Save(Inventory, inventory);
await interaction.reply(`${card.card.name} given to ${user.username}, they now have ${inventory.Quantity}`);
await interaction.reply(`Card ${card.card.name} given to ${user.username}, they now have ${inventory.Quantity}`);
}
private async GiveCurrency(interaction: CommandInteraction) {
const amount = interaction.options.get("amount", true);
const user = interaction.options.getUser("user", true);
AppLogger.LogSilly("Commands/Give/GiveCurrency", `Parameters: amount=${amount.value} user=${user.id}`);
const userEntity = await User.FetchOneById(User, user.id) || new User(user.id, 300);
userEntity.AddCurrency(amount.value! as number);
await userEntity.Save(User, userEntity);
await interaction.reply(`${amount.value} currency ${amount.value! as number >= 0 ? "given to" : "taken from"} ${user.username}, they now have ${userEntity.Currency}`);
}
}

73
src/commands/sacrifice.ts Normal file
View file

@ -0,0 +1,73 @@
import { ActionRowBuilder, ButtonBuilder, ButtonStyle, CacheType, CommandInteraction, EmbedBuilder, SlashCommandBuilder } from "discord.js";
import { Command } from "../type/command";
import Inventory from "../database/entities/app/Inventory";
import { CardRarityToString, GetSacrificeAmount } from "../constants/CardRarity";
import CardDropHelperMetadata from "../helpers/CardDropHelperMetadata";
import EmbedColours from "../constants/EmbedColours";
export default class Sacrifice extends Command {
constructor() {
super();
this.CommandBuilder = new SlashCommandBuilder()
.setName("sacrifice")
.setDescription("Sacrifices a card for currency")
.addStringOption(x =>
x
.setName("cardnumber")
.setDescription("The card to sacrifice from your inventory")
.setRequired(true));
}
public override async execute(interaction: CommandInteraction<CacheType>): Promise<void> {
const cardnumber = interaction.options.get("cardnumber", true);
const cardInInventory = await Inventory.FetchOneByCardNumberAndUserId(interaction.user.id, cardnumber.value! as string);
if (!cardInInventory || cardInInventory.Quantity == 0) {
await interaction.reply("Unable to find card in your inventory.");
return;
}
const cardData = CardDropHelperMetadata.GetCardByCardNumber(cardnumber.value! as string);
if (!cardData) {
await interaction.reply("Unable to find card in the database.");
return;
}
const cardValue = GetSacrificeAmount(cardData.card.type);
const cardRarityString = CardRarityToString(cardData.card.type);
const description = [
`Card: ${cardData.card.name}`,
`Series: ${cardData.series.name}`,
`Rarity: ${cardRarityString}`,
`Quantity Owned: ${cardInInventory.Quantity}`,
`Sacrifice Amount: ${cardValue}`,
];
const embed = new EmbedBuilder()
.setTitle("Sacrifice")
.setDescription(description.join("\n"))
.setColor(EmbedColours.Error)
.setFooter({ text: `${interaction.user.username}` });
const row = new ActionRowBuilder<ButtonBuilder>()
.addComponents([
new ButtonBuilder()
.setCustomId(`sacrifice confirm ${interaction.user.id} ${cardnumber.value!}`)
.setLabel("Confirm")
.setStyle(ButtonStyle.Success),
new ButtonBuilder()
.setCustomId(`sacrifice cancel ${interaction.user.id} ${cardnumber.value!}`)
.setLabel("Cancel")
.setStyle(ButtonStyle.Secondary),
]);
await interaction.reply({
embeds: [ embed ],
components: [ row ],
});
}
}

View file

@ -0,0 +1,6 @@
export default class CardConstants {
public static readonly ClaimCost = 10;
public static readonly TimerGiveAmount = 10;
public static readonly DailyCurrency = 100;
public static readonly StartingCurrency = 300;
}

View file

@ -58,4 +58,21 @@ export function CardRarityParse(rarity: string): CardRarity {
default:
return CardRarity.Unknown;
}
}
export function GetSacrificeAmount(rarity: CardRarity): number {
switch (rarity) {
case CardRarity.Bronze:
return 5;
case CardRarity.Silver:
return 15;
case CardRarity.Gold:
return 30;
case CardRarity.Manga:
return 50;
case CardRarity.Legendary:
return 100;
default:
return 0;
}
}

View file

@ -1,8 +1,14 @@
export default class EmbedColours {
// General
public static readonly Ok = 0x3050ba;
public static readonly Success = 0x50c878;
public static readonly Error = 0xff0000;
// Colours
public static readonly Grey = 0xd3d3d3;
public static readonly Green = 0x228B22;
// Card Types
public static readonly BronzeCard = 0xcd7f32;
public static readonly SilverCard = 0xc0c0c0;
public static readonly GoldCard = 0xffd700;

View file

@ -27,6 +27,12 @@ export default class AppBaseEntity {
await repository.save(entity);
}
public static async SaveAll<T extends AppBaseEntity>(target: EntityTarget<T>, entities: DeepPartial<T>[]): Promise<void> {
const repository = AppDataSource.getRepository<T>(target);
await repository.save(entities);
}
public static async Remove<T extends AppBaseEntity>(target: EntityTarget<T>, entity: T): Promise<void> {
const repository = AppDataSource.getRepository<T>(target);

View file

@ -29,6 +29,12 @@ export default class Inventory extends AppBaseEntity {
this.Quantity = quantity;
}
public RemoveQuantity(amount: number) {
if (this.Quantity < amount) return;
this.Quantity -= amount;
}
public AddClaim(claim: Claim) {
this.Claims.push(claim);
}

View file

@ -13,7 +13,22 @@ export default class User extends AppBaseEntity {
@Column()
Currency: number;
public UpdateCurrency(currency: number) {
this.Currency = currency;
@Column()
LastUsedDaily?: Date;
public AddCurrency(amount: number) {
this.Currency += amount;
}
public RemoveCurrency(amount: number): boolean {
if (this.Currency < amount) return false;
this.Currency -= amount;
return true;
}
public UpdateLastUsedDaily(lastUsedDaily: Date) {
this.LastUsedDaily = lastUsedDaily;
}
}

View file

@ -0,0 +1,15 @@
import { MigrationInterface, QueryRunner } from "typeorm";
import MigrationHelper from "../../../../helpers/MigrationHelper";
export class Daily1715967355818 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
MigrationHelper.Up("1715967355818-daily", "0.6", [
"01-table/User",
], queryRunner);
}
public async down(): Promise<void> {
}
}

View file

@ -35,7 +35,8 @@ export default class InventoryHelper {
.filter(x => {
x.cards = x.cards
.sort((a, b) => b.type - a.type)
.filter(y => inventory.find(z => z.CardNumber == y.id));
.filter(y => inventory.find(z => z.CardNumber == y.id))
.filter(y => inventory.find(z => z.CardNumber == y.id)!.Quantity > 0);
return x;
});

View file

@ -0,0 +1,81 @@
import { CronJob } from "cron";
import { v4 } from "uuid";
import { Primitive } from "../type/primitive";
interface Timer {
id: string;
job: CronJob;
context: Map<string, Primitive>;
onTick: ((context: Map<string, Primitive>) => void) | ((context: Map<string, Primitive>) => Promise<void>);
runOnStart: boolean;
}
export default class TimerHelper {
private _timers: Timer[];
constructor() {
this._timers = [];
}
public AddTimer(
cronTime: string,
timeZone: string,
onTick: ((context: Map<string, Primitive>) => void) | ((context: Map<string, Primitive>) => Promise<void>),
runOnStart: boolean = false): string {
const context = new Map<string, Primitive>();
const job = new CronJob(
cronTime,
() => {
onTick(context);
},
null,
false,
timeZone,
);
const id = v4();
this._timers.push({
id,
job,
context,
onTick,
runOnStart,
});
return id;
}
public StartAllTimers() {
this._timers.forEach(timer => this.StartJob(timer));
}
public StopAllTimers() {
this._timers.forEach(timer => timer.job.stop());
}
public StartTimer(id: string) {
const timer = this._timers.find(x => x.id == id);
if (!timer) return;
this.StartJob(timer);
}
public StopTimer(id: string) {
const timer = this._timers.find(x => x.id == id);
if (!timer) return;
timer.job.stop();
}
private StartJob(timer: Timer) {
timer.job.start();
if (timer.runOnStart) {
timer.onTick(timer.context);
}
}
}

View file

@ -3,11 +3,14 @@ import { Environment } from "./constants/Environment";
// Global Command Imports
import About from "./commands/about";
import Balance from "./commands/balance";
import Daily from "./commands/daily";
import Drop from "./commands/drop";
import Gdrivesync from "./commands/gdrivesync";
import Give from "./commands/give";
import Inventory from "./commands/inventory";
import Resync from "./commands/resync";
import Sacrifice from "./commands/sacrifice";
import Series from "./commands/series";
import Trade from "./commands/trade";
import View from "./commands/view";
@ -20,6 +23,7 @@ import Droprarity from "./commands/stage/droprarity";
import Claim from "./buttonEvents/Claim";
import InventoryButtonEvent from "./buttonEvents/Inventory";
import Reroll from "./buttonEvents/Reroll";
import SacrificeButtonEvent from "./buttonEvents/Sacrifice";
import SeriesEvent from "./buttonEvents/Series";
import TradeButtonEvent from "./buttonEvents/Trade";
@ -27,11 +31,14 @@ export default class Registry {
public static RegisterCommands() {
// Global Commands
CoreClient.RegisterCommand("about", new About());
CoreClient.RegisterCommand("balance", new Balance());
CoreClient.RegisterCommand("daily", new Daily());
CoreClient.RegisterCommand("drop", new Drop());
CoreClient.RegisterCommand("gdrivesync", new Gdrivesync());
CoreClient.RegisterCommand("give", new Give());
CoreClient.RegisterCommand("inventory", new Inventory());
CoreClient.RegisterCommand("resync", new Resync());
CoreClient.RegisterCommand("sacrifice", new Sacrifice());
CoreClient.RegisterCommand("series", new Series());
CoreClient.RegisterCommand("trade", new Trade());
CoreClient.RegisterCommand("view", new View());
@ -41,14 +48,11 @@ export default class Registry {
CoreClient.RegisterCommand("droprarity", new Droprarity(), Environment.Test);
}
public static RegisterEvents() {
}
public static RegisterButtonEvents() {
CoreClient.RegisterButtonEvent("claim", new Claim());
CoreClient.RegisterButtonEvent("inventory", new InventoryButtonEvent());
CoreClient.RegisterButtonEvent("reroll", new Reroll());
CoreClient.RegisterButtonEvent("sacrifice", new SacrificeButtonEvent());
CoreClient.RegisterButtonEvent("series", new SeriesEvent());
CoreClient.RegisterButtonEvent("trade", new TradeButtonEvent());
}

View file

@ -0,0 +1,17 @@
import AppLogger from "../client/appLogger";
import CardConstants from "../constants/CardConstants";
import User from "../database/entities/app/User";
export default async function GiveCurrency() {
AppLogger.LogInfo("Timers/GiveCurrency", "Giving currency to every known user");
const users = await User.FetchAll(User);
for (const user of users) {
user.AddCurrency(CardConstants.TimerGiveAmount);
}
User.SaveAll(User, users);
AppLogger.LogInfo("Timers/GiveCurrency", `Successfully gave +${CardConstants.TimerGiveAmount} currency to ${users.length} users`);
}

View file

@ -1,7 +1,8 @@
import { CommandInteraction, SlashCommandBuilder } from "discord.js";
import { CommandInteraction } from "discord.js";
export abstract class Command {
public CommandBuilder: Omit<SlashCommandBuilder, "addSubcommand" | "addSubcommandGroup">;
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- CommandBuilder type is dynamic depending on options and can't be strictly typed
public CommandBuilder: any;
abstract execute(interaction: CommandInteraction): Promise<void>;
}

1
src/type/primitive.ts Normal file
View file

@ -0,0 +1 @@
export type Primitive = string | number | boolean;