Compare commits

...

131 commits
v0.3.0 ... main

Author SHA1 Message Date
Ethan Lane 53656ba0da v0.6.4
All checks were successful
Deploy To Production / build (push) Successful in 8s
Deploy To Production / deploy (push) Successful in 14s
2024-06-15 21:01:28 +01:00
Ethan Lane 27b6224b5e 0.6.4 2024-06-15 21:01:22 +01:00
Ethan Lane e584c1291b Fix the claim logic removing a user's currency before it checks if the card is actually claimable
All checks were successful
Test / build (push) Successful in 7s
2024-06-15 21:00:14 +01:00
Ethan Lane 976445fa0d v0.6.3
All checks were successful
Deploy To Production / build (push) Successful in 8s
Deploy To Production / deploy (push) Successful in 14s
2024-06-07 18:12:38 +01:00
Ethan Lane 27a4019f00 0.6.3 2024-06-07 18:12:13 +01:00
Ethan Lane f6c744cdcf Update the give currency timer to only give currency to those with less than 1000 currency
All checks were successful
Test / build (push) Successful in 7s
2024-06-07 18:11:27 +01:00
Ethan Lane a03a62277d Update trade command so the usernames are more obvious
All checks were successful
Test / build (push) Successful in 8s
2024-06-05 19:25:27 +01:00
Ethan Lane 75315b3db2 v0.6.2
All checks were successful
Deploy To Production / build (push) Successful in 7s
Deploy To Production / deploy (push) Successful in 15s
2024-06-03 18:44:33 +01:00
Ethan Lane 25f605e623 0.6.2 2024-06-03 18:44:26 +01:00
Ethan Lane 1395a65344 Fix linter
All checks were successful
Test / build (push) Successful in 8s
2024-06-03 18:43:18 +01:00
Ethan Lane fd16500315 Fix build 2024-06-03 18:42:01 +01:00
Ethan Lane a581bf9d80 Migrate to yarn 2024-06-03 18:36:09 +01:00
Ethan Lane 1b707c4517 Rebalance the sacrifice amounts 2024-06-03 18:33:06 +01:00
Ethan Lane 5c6c0e65c3 0.6.1
All checks were successful
Deploy To Production / build (push) Successful in 2m29s
Deploy To Production / deploy (push) Successful in 16s
Deploy To Stage / build (push) Successful in 11s
Deploy To Stage / deploy (push) Successful in 18s
2024-06-02 16:16:19 +01:00
Ethan Lane ebec66607f 0.6.1 2024-06-02 16:11:05 +01:00
Ethan Lane f12bb11ffb Fix a user being able to make a trade with themself
All checks were successful
Test / build (push) Successful in 2m29s
2024-06-02 16:05:05 +01:00
Ethan Lane 837013835e Fix user being able to claim cards with a 0 balance 2024-06-02 15:39:24 +01:00
Ethan Lane 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
Ethan Lane 302a762912 0.6.0 2024-06-01 18:07:04 +01:00
Ethan Lane 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
Ethan Lane 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
Ethan Lane 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
Ethan Lane 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
Ethan Lane 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
Ethan Lane 34ea1f87d7 0.5.2
All checks were successful
Deploy To Production / build (push) Successful in 2m27s
Deploy To Production / deploy (push) Successful in 17s
2024-05-30 17:34:22 +01:00
Ethan Lane ba9ade0659 0.5.2
All checks were successful
Test / build (push) Successful in 2m28s
2024-05-30 17:28:43 +01:00
Ethan Lane 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
Ethan Lane 297e34e1cf Fix bug where large file attachments would cause claiming to fail interaction
All checks were successful
Test / build (push) Successful in 2m28s
2024-05-29 17:36:58 +01:00
RenovateBot 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
Ethan Lane 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
Ethan Lane 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
Ethan Lane 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
RenovateBot 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
RenovateBot 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
Vylpes 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
Ethan Lane 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
RenovateBot 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
RenovateBot 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
Ethan Lane 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
RenovateBot 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
RenovateBot 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
Ethan Lane 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
RenovateBot 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
RenovateBot 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
Ethan Lane c6d78cc370 Source .sshrc
All checks were successful
Deploy To Stage / build (push) Successful in 10s
Deploy To Stage / deploy (push) Successful in 14s
Deploy To Production / build (push) Successful in 12s
Deploy To Production / deploy (push) Successful in 16s
2024-04-28 17:40:00 +01:00
Ethan Lane 33a8b85580 Runs on node
Some checks failed
Deploy To Stage / build (push) Successful in 2m29s
Deploy To Stage / deploy (push) Failing after 15s
2024-04-28 17:36:36 +01:00
Ethan Lane ed42ceaca4 Migrate to forgejo runner
Some checks failed
Deploy To Stage / build (push) Has been cancelled
Deploy To Stage / deploy (push) Has been cancelled
2024-04-28 17:34:42 +01:00
Ethan Lane 2bce901d63 Create concept of currency in the database (#209)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
# 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 the concept of currency in the database

#200

## 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: https://gitea.vylpes.xyz/External/card-drop/pulls/209
Reviewed-by: VylpesTester <tester@vylpes.com>
Co-authored-by: Ethan Lane <ethan@vylpes.com>
Co-committed-by: Ethan Lane <ethan@vylpes.com>
2024-04-26 18:35:03 +01:00
RenovateBot 8aa4fc340a Update dependency winston to v3.13.0 (#212)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [winston](https://github.com/winstonjs/winston) | dependencies | minor | [`3.11.0` -> `3.13.0`](https://renovatebot.com/diffs/npm/winston/3.11.0/3.13.0) |

---

### Release Notes

<details>
<summary>winstonjs/winston (winston)</summary>

### [`v3.13.0`](https://github.com/winstonjs/winston/releases/tag/v3.13.0)

[Compare Source](https://github.com/winstonjs/winston/compare/v3.12.1...v3.13.0)

-   fix(http): allow passing maximumDepth to prevent big object being stringified ([#&#8203;2425](https://github.com/winstonjs/winston/issues/2425))  [`a237865`](https://github.com/winstonjs/winston/commit/a237865)

### [`v3.12.1`](https://github.com/winstonjs/winston/releases/tag/v3.12.1)

[Compare Source](https://github.com/winstonjs/winston/compare/v3.12.0...v3.12.1)

-   Bump [@&#8203;types/node](https://github.com/types/node) from 20.11.24 to 20.11.29 ([#&#8203;2431](https://github.com/winstonjs/winston/issues/2431))  [`b10b98f`](https://github.com/winstonjs/winston/commit/b10b98f)
-   Revert "Remove nonexistent Logger methods from types" ([#&#8203;2434](https://github.com/winstonjs/winston/issues/2434))  [`0277035`](https://github.com/winstonjs/winston/commit/0277035)
-   fixed flaky test case ([#&#8203;2412](https://github.com/winstonjs/winston/issues/2412))  [`d95c948`](https://github.com/winstonjs/winston/commit/d95c948)

### [`v3.12.0`](https://github.com/winstonjs/winston/releases/tag/v3.12.0)

[Compare Source](https://github.com/winstonjs/winston/compare/v3.11.0...v3.12.0)

-   missing timestamp format in ready-to-use-pattern example ([#&#8203;2421](https://github.com/winstonjs/winston/issues/2421))  [`9e5b407`](https://github.com/winstonjs/winston/commit/9e5b407)
-   bump deps ([#&#8203;2422](https://github.com/winstonjs/winston/issues/2422))  [`4a85e6b`](https://github.com/winstonjs/winston/commit/4a85e6b)
-   \[chore] Run coveralls CI check on Node 20 not 16 ([#&#8203;2418](https://github.com/winstonjs/winston/issues/2418))  [`e153c68`](https://github.com/winstonjs/winston/commit/e153c68)
-   Bump [@&#8203;types/node](https://github.com/types/node) from 20.8.6 to 20.11.19 ([#&#8203;2413](https://github.com/winstonjs/winston/issues/2413))  [`587f40f`](https://github.com/winstonjs/winston/commit/587f40f)
-   Update README.md ([#&#8203;2417](https://github.com/winstonjs/winston/issues/2417))  [`8e99a00`](https://github.com/winstonjs/winston/commit/8e99a00)
-   docs: fix anchor in transports docs ([#&#8203;2416](https://github.com/winstonjs/winston/issues/2416))  [`0bde36b`](https://github.com/winstonjs/winston/commit/0bde36b)
-   add winston-transport-vscode to transports docs ([#&#8203;2411](https://github.com/winstonjs/winston/issues/2411))  [`8fb5b41`](https://github.com/winstonjs/winston/commit/8fb5b41)
-   Bump [@&#8203;babel/cli](https://github.com/babel/cli) from 7.23.0 to 7.23.9 ([#&#8203;2406](https://github.com/winstonjs/winston/issues/2406))  [`a326743`](https://github.com/winstonjs/winston/commit/a326743)
-   Add winston-newrelic-agent-transport to transport documentation ([#&#8203;2382](https://github.com/winstonjs/winston/issues/2382))  [`cc731ef`](https://github.com/winstonjs/winston/commit/cc731ef)
-   Remove newrelic-winston transport entry. ([#&#8203;2405](https://github.com/winstonjs/winston/issues/2405))  [`f077f30`](https://github.com/winstonjs/winston/commit/f077f30)
-   Bump eslint from 8.55.0 to 8.56.0 ([#&#8203;2397](https://github.com/winstonjs/winston/issues/2397))  [`3943c41`](https://github.com/winstonjs/winston/commit/3943c41)
-   Bump the npm_and_yarn group group with 1 update ([#&#8203;2391](https://github.com/winstonjs/winston/issues/2391))  [`8260866`](https://github.com/winstonjs/winston/commit/8260866)
-   Fix unhandled rejection handling ([#&#8203;2390](https://github.com/winstonjs/winston/issues/2390))  [`333b763`](https://github.com/winstonjs/winston/commit/333b763)
-   Fix all rimraf usages to the best of my ability; glob is not true by default in rimraf; file archive test only passed every other time using async rimraf, could use further investigation  [`c3f3b5b`](https://github.com/winstonjs/winston/commit/c3f3b5b)
-   Fix rimraf usage in new test  [`8f3c653`](https://github.com/winstonjs/winston/commit/8f3c653)
-   Fix rimraf import in test (why didn't this break in PR CI?)  [`f3836aa`](https://github.com/winstonjs/winston/commit/f3836aa)
-   Added functionality to long broken zippedArchive option ([#&#8203;2337](https://github.com/winstonjs/winston/issues/2337))  [`02d4267`](https://github.com/winstonjs/winston/commit/02d4267)
-   Bump async from 3.2.4 to 3.2.5 ([#&#8203;2378](https://github.com/winstonjs/winston/issues/2378))  [`069a40d`](https://github.com/winstonjs/winston/commit/069a40d)
-   Bump [@&#8203;babel/preset-env](https://github.com/babel/preset-env) from 7.23.2 to 7.23.7 ([#&#8203;2384](https://github.com/winstonjs/winston/issues/2384))  [`79282e1`](https://github.com/winstonjs/winston/commit/79282e1)
-   Bump winston-transport; fix test issue ([#&#8203;2386](https://github.com/winstonjs/winston/issues/2386))  [`05788b9`](https://github.com/winstonjs/winston/commit/05788b9)
-   Bump eslint from 8.51.0 to 8.55.0 ([#&#8203;2375](https://github.com/winstonjs/winston/issues/2375))  [`a7c2eec`](https://github.com/winstonjs/winston/commit/a7c2eec)
-   Bump std-mocks from 1.0.1 to 2.0.0 ([#&#8203;2361](https://github.com/winstonjs/winston/issues/2361))  [`85c336e`](https://github.com/winstonjs/winston/commit/85c336e)
-   Bump actions/setup-node from 3 to 4 ([#&#8203;2362](https://github.com/winstonjs/winston/issues/2362))  [`448d11c`](https://github.com/winstonjs/winston/commit/448d11c)
-   chore(README.md): adds documentation around coloring json formatted logs  [`91ec069`](https://github.com/winstonjs/winston/commit/91ec069)
-   Remove nonexistent Logger methods from types  [`c3c3911`](https://github.com/winstonjs/winston/commit/c3c3911)
-   Update dependencies  [`caf2df6`](https://github.com/winstonjs/winston/commit/caf2df6)

</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: https://gitea.vylpes.xyz/External/card-drop/pulls/212
Reviewed-by: Vylpes <ethan@vylpes.com>
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-04-23 19:47:13 +01:00
Ethan Lane ea9c8c5247 Update woodpecker config to use new ip
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-04-23 19:42:33 +01:00
RenovateBot 14929b1aed Update dependency typescript to v5.4.5 (#211)
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [typescript](https://www.typescriptlang.org/) ([source](https://github.com/Microsoft/TypeScript)) | devDependencies | minor | [`5.3.3` -> `5.4.5`](https://renovatebot.com/diffs/npm/typescript/5.3.3/5.4.5) |

---

### Release Notes

<details>
<summary>Microsoft/TypeScript (typescript)</summary>

### [`v5.4.5`](https://github.com/microsoft/TypeScript/releases/tag/v5.4.5): TypeScript 5.4.5

[Compare Source](https://github.com/Microsoft/TypeScript/compare/v5.4.4...v5.4.5)

For release notes, check out the [release announcement](https://devblogs.microsoft.com/typescript/announcing-typescript-5-4/).

For the complete list of fixed issues, check out the

-   [fixed issues query for Typescript 5.4.0 (Beta)](https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93\&q=milestone%3A%22TypeScript+5.4.0%22+is%3Aclosed+).
-   [fixed issues query for Typescript 5.4.1 (RC)](https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93\&q=milestone%3A%22TypeScript+5.4.1%22+is%3Aclosed+).
-   [fixed issues query for Typescript 5.4.2 (Stable)](https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93\&q=milestone%3A%22TypeScript+5.4.2%22+is%3Aclosed+).
-   [fixed issues query for Typescript 5.4.3 (Stable)](https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93\&q=milestone%3A%22TypeScript+5.4.3%22+is%3Aclosed+).
-   [fixed issues query for Typescript 5.4.4 (Stable)](https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93\&q=milestone%3A%22TypeScript+5.4.4%22+is%3Aclosed+).
-   [fixed issues query for Typescript 5.4.5 (Stable)](https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93\&q=milestone%3A%22TypeScript+5.4.5%22+is%3Aclosed+).

Downloads are available on:

-   [NuGet package](https://www.nuget.org/packages/Microsoft.TypeScript.MSBuild)

### [`v5.4.4`](https://github.com/microsoft/TypeScript/releases/tag/v5.4.4): TypeScript 5.4.4

[Compare Source](https://github.com/Microsoft/TypeScript/compare/v5.4.3...v5.4.4)

For release notes, check out the [release announcement](https://devblogs.microsoft.com/typescript/announcing-typescript-5-4/).

For the complete list of fixed issues, check out the

-   [fixed issues query for Typescript 5.4.0 (Beta)](https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93\&q=milestone%3A%22TypeScript+5.4.0%22+is%3Aclosed+).
-   [fixed issues query for Typescript 5.4.1 (RC)](https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93\&q=milestone%3A%22TypeScript+5.4.1%22+is%3Aclosed+).
-   [fixed issues query for Typescript 5.4.2 (Stable)](https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93\&q=milestone%3A%22TypeScript+5.4.2%22+is%3Aclosed+).
-   [fixed issues query for Typescript 5.4.3 (Stable)](https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93\&q=milestone%3A%22TypeScript+5.4.3%22+is%3Aclosed+).
-   [fixed issues query for Typescript 5.4.4 (Stable)](https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93\&q=milestone%3A%22TypeScript+5.4.4%22+is%3Aclosed+).

Downloads are available on:

-   [NuGet package](https://www.nuget.org/packages/Microsoft.TypeScript.MSBuild)

### [`v5.4.3`](https://github.com/microsoft/TypeScript/releases/tag/v5.4.3): TypeScript 5.4.3

[Compare Source](https://github.com/Microsoft/TypeScript/compare/v5.4.2...v5.4.3)

For release notes, check out the [release announcement](https://devblogs.microsoft.com/typescript/announcing-typescript-5-4/).

For the complete list of fixed issues, check out the

-   [fixed issues query for Typescript 5.4.0 (Beta)](https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93\&q=milestone%3A%22TypeScript+5.4.0%22+is%3Aclosed+).
-   [fixed issues query for Typescript 5.4.1 (RC)](https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93\&q=milestone%3A%22TypeScript+5.4.1%22+is%3Aclosed+).
-   [fixed issues query for Typescript 5.4.2 (Stable)](https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93\&q=milestone%3A%22TypeScript+5.4.2%22+is%3Aclosed+).
-   [fixed issues query for Typescript 5.4.3 (Stable)](https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93\&q=milestone%3A%22TypeScript+5.4.3%22+is%3Aclosed+).

Downloads are available on:

-   [NuGet package](https://www.nuget.org/packages/Microsoft.TypeScript.MSBuild)

### [`v5.4.2`](https://github.com/microsoft/TypeScript/releases/tag/v5.4.2): TypeScript 5.4

[Compare Source](https://github.com/Microsoft/TypeScript/compare/v5.3.3...v5.4.2)

For release notes, check out the [release announcement](https://devblogs.microsoft.com/typescript/announcing-typescript-5-4/).

For the complete list of fixed issues, check out the

-   [fixed issues query for Typescript 5.4.0 (Beta)](https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93\&q=milestone%3A%22TypeScript+5.4.0%22+is%3Aclosed+).
-   [fixed issues query for Typescript 5.4.1 (RC)](https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93\&q=milestone%3A%22TypeScript+5.4.1%22+is%3Aclosed+).
-   [fixed issues query for Typescript 5.4.2 (Stable)](https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93\&q=milestone%3A%22TypeScript+5.4.2%22+is%3Aclosed+).

Downloads are available on:

-   [NuGet package](https://www.nuget.org/packages/Microsoft.TypeScript.MSBuild)

</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: https://gitea.vylpes.xyz/External/card-drop/pulls/211
Reviewed-by: Vylpes <ethan@vylpes.com>
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-04-23 19:36:46 +01:00
RenovateBot bcbd0855b8 Update dependency jest-mock-extended to v3.0.6 (#208)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This PR contains the following updates:

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

---

### Release Notes

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

### [`v3.0.6`](https://github.com/marchaos/jest-mock-extended/compare/3.0.5...77a64ae8328904bcc614ead4ba8d0d9e8a658136)

[Compare Source](https://github.com/marchaos/jest-mock-extended/compare/3.0.5...77a64ae8328904bcc614ead4ba8d0d9e8a658136)

</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: https://gitea.vylpes.xyz/External/card-drop/pulls/208
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-04-16 18:17:26 +01:00
RenovateBot 22cd98f229 Update dependency @types/node to v20.12.7 (#207)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
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.5` -> `20.12.7`](https://renovatebot.com/diffs/npm/@types%2fnode/20.12.5/20.12.7) |

---

### 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: https://gitea.vylpes.xyz/External/card-drop/pulls/207
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-04-16 18:16:09 +01:00
RenovateBot cda41d87c3 Update dependency @types/node to v20.12.5 (#196)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
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 | minor | [`20.11.30` -> `20.12.5`](https://renovatebot.com/diffs/npm/@types%2fnode/20.11.30/20.12.5) |

---

### 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: https://gitea.vylpes.xyz/External/card-drop/pulls/196
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-04-08 15:12:50 +01:00
RenovateBot b14fac2c58 Update dependency minimatch to v9.0.4 (#195)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [minimatch](https://github.com/isaacs/minimatch) | dependencies | patch | [`9.0.3` -> `9.0.4`](https://renovatebot.com/diffs/npm/minimatch/9.0.3/9.0.4) |

---

### Release Notes

<details>
<summary>isaacs/minimatch (minimatch)</summary>

### [`v9.0.4`](https://github.com/isaacs/minimatch/compare/v9.0.3...v9.0.4)

[Compare Source](https://github.com/isaacs/minimatch/compare/v9.0.3...v9.0.4)

</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: https://gitea.vylpes.xyz/External/card-drop/pulls/195
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-04-08 15:10:40 +01:00
RenovateBot 5c905e3a87 Update dependency glob to v10.3.12 (#193)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This PR contains the following updates:

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

---

### Release Notes

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

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

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

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

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

</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: https://gitea.vylpes.xyz/External/card-drop/pulls/193
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-04-01 18:04:59 +01:00
RenovateBot b1d2daa871 Update dependency express to v4.19.2 (#192)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [express](http://expressjs.com/) ([source](https://github.com/expressjs/express)) | dependencies | patch | [`4.19.1` -> `4.19.2`](https://renovatebot.com/diffs/npm/express/4.19.1/4.19.2) |

---

### Release Notes

<details>
<summary>expressjs/express (express)</summary>

### [`v4.19.2`](https://github.com/expressjs/express/blob/HEAD/History.md#4192--2024-03-25)

[Compare Source](https://github.com/expressjs/express/compare/4.19.1...4.19.2)

\==========

-   Improved fix for open redirect allow list bypass

</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: https://gitea.vylpes.xyz/External/card-drop/pulls/192
Reviewed-by: Vylpes <ethan@vylpes.com>
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-04-01 18:03:49 +01:00
Ethan Lane c7b01c932e Update claim event to increment the claimed number when the user claims a drop (#191)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
# 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 claim event to increment the claim number when the user claims a drop
- Due to discord api limitations I can't reply to an interaction and edit the embed, so I've had to change it so the claimed by is displayed in the same embed
- This also has the nice side effect of letting me disable the claim button as well

#89

## 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: https://gitea.vylpes.xyz/External/card-drop/pulls/191
Reviewed-by: VylpesTester <tester@vylpes.com>
Co-authored-by: Ethan Lane <ethan@vylpes.com>
Co-committed-by: Ethan Lane <ethan@vylpes.com>
2024-03-31 15:51:10 +01:00
Ethan Lane 16857ef14d Create series command (#190)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
# 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 series list command to let users view all series in the bot
- Create series view command to let users view cards in a specific series
- Both commands have a paginated event so the embeds don't get too big

#99

## 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: https://gitea.vylpes.xyz/External/card-drop/pulls/190
Reviewed-by: VylpesTester <tester@vylpes.com>
Co-authored-by: Ethan Lane <ethan@vylpes.com>
Co-committed-by: Ethan Lane <ethan@vylpes.com>
2024-03-31 15:49:30 +01:00
RenovateBot 94f285541b Update dependency express to v4.19.1 (#189)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [express](http://expressjs.com/) ([source](https://github.com/expressjs/express)) | dependencies | minor | [`4.18.3` -> `4.19.1`](https://renovatebot.com/diffs/npm/express/4.18.3/4.19.1) |

---

### Release Notes

<details>
<summary>expressjs/express (express)</summary>

### [`v4.19.1`](https://github.com/expressjs/express/blob/HEAD/History.md#4191--2024-03-20)

[Compare Source](https://github.com/expressjs/express/compare/4.19.0...4.19.1)

\==========

-   Allow passing non-strings to res.location with new encoding handling checks

### [`v4.19.0`](https://github.com/expressjs/express/blob/HEAD/History.md#4190--2024-03-20)

[Compare Source](https://github.com/expressjs/express/compare/4.18.3...4.19.0)

\==========

-   Prevent open redirect allow list bypass due to encodeurl
-   deps: cookie@0.6.0

</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: https://gitea.vylpes.xyz/External/card-drop/pulls/189
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-03-25 18:42:21 +00:00
RenovateBot 48f4bf095b Update dependency @types/node to v20.11.30 (#188)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
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.11.28` -> `20.11.30`](https://renovatebot.com/diffs/npm/@types%2fnode/20.11.28/20.11.30) |

---

### 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: https://gitea.vylpes.xyz/External/card-drop/pulls/188
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-03-25 18:40:52 +00:00
RenovateBot dead9545ba Update dependency eslint to v8.57.0 (#186)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [eslint](https://eslint.org) ([source](https://github.com/eslint/eslint)) | devDependencies | minor | [`8.56.0` -> `8.57.0`](https://renovatebot.com/diffs/npm/eslint/8.56.0/8.57.0) |

---

### Release Notes

<details>
<summary>eslint/eslint (eslint)</summary>

### [`v8.57.0`](https://github.com/eslint/eslint/releases/tag/v8.57.0)

[Compare Source](https://github.com/eslint/eslint/compare/v8.56.0...v8.57.0)

#### Features

-   [`1120b9b`](1120b9b7b9) feat: Add loadESLint() API method for v8 ([#&#8203;18098](https://github.com/eslint/eslint/issues/18098)) (Nicholas C. Zakas)
-   [`dca7d0f`](dca7d0f1c2) feat: Enable `eslint.config.mjs` and `eslint.config.cjs` ([#&#8203;18066](https://github.com/eslint/eslint/issues/18066)) (Nitin Kumar)

#### Bug Fixes

-   [`2196d97`](2196d97094) fix: handle absolute file paths in `FlatRuleTester` ([#&#8203;18064](https://github.com/eslint/eslint/issues/18064)) (Nitin Kumar)
-   [`69dd1d1`](69dd1d1387) fix: Ensure config keys are printed for config errors ([#&#8203;18067](https://github.com/eslint/eslint/issues/18067)) (Nitin Kumar)
-   [`9852a31`](9852a31edc) fix: deep merge behavior in flat config ([#&#8203;18065](https://github.com/eslint/eslint/issues/18065)) (Nitin Kumar)
-   [`4c7e9b0`](4c7e9b0b53) fix: allow circular references in config ([#&#8203;18056](https://github.com/eslint/eslint/issues/18056)) (Milos Djermanovic)

#### Documentation

-   [`84922d0`](84922d0bfa) docs: Show prerelease version in dropdown ([#&#8203;18139](https://github.com/eslint/eslint/issues/18139)) (Nicholas C. Zakas)
-   [`5b8c363`](5b8c3636a3) docs: Switch to Ethical Ads ([#&#8203;18117](https://github.com/eslint/eslint/issues/18117)) (Milos Djermanovic)
-   [`77dbfd9`](77dbfd9887) docs: show NEXT in version selectors ([#&#8203;18052](https://github.com/eslint/eslint/issues/18052)) (Milos Djermanovic)

#### Chores

-   [`1813aec`](1813aecc46) chore: upgrade [@&#8203;eslint/js](https://github.com/eslint/js)[@&#8203;8](https://github.com/8).57.0 ([#&#8203;18143](https://github.com/eslint/eslint/issues/18143)) (Milos Djermanovic)
-   [`5c356bb`](5c356bb0c6) chore: package.json update for [@&#8203;eslint/js](https://github.com/eslint/js) release (Jenkins)
-   [`f4a1fe2`](f4a1fe2e45) test: add more tests for ignoring files and directories ([#&#8203;18068](https://github.com/eslint/eslint/issues/18068)) (Nitin Kumar)
-   [`42c0aef`](42c0aefaf6) ci: Enable CI for `v8.x` branch ([#&#8203;18047](https://github.com/eslint/eslint/issues/18047)) (Milos Djermanovic)

</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: https://gitea.vylpes.xyz/External/card-drop/pulls/186
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-03-21 17:55:09 +00:00
RenovateBot 76f1dbaba5 Update dependency @types/node to v20.11.28 (#185)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
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.11.25` -> `20.11.28`](https://renovatebot.com/diffs/npm/@types%2fnode/20.11.25/20.11.28) |

---

### 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: https://gitea.vylpes.xyz/External/card-drop/pulls/185
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-03-21 17:51:49 +00:00
Ethan Lane 5dd50a3f3b Add logger to project (#183)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
# 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.

- Add the winston package to handle logging
- Add logging to the project's logic

#146

## 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: https://gitea.vylpes.xyz/External/card-drop/pulls/183
Reviewed-by: VylpesTester <tester@vylpes.com>
Co-authored-by: Ethan Lane <ethan@vylpes.com>
Co-committed-by: Ethan Lane <ethan@vylpes.com>
2024-03-15 17:33:12 +00:00
Ethan Lane 42dfe2d047 Merge branch 'main' into develop
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-14 17:36:46 +00:00
Ethan Lane 370730cbea 0.5.1
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-14 17:36:26 +00:00
Ethan Lane e0479127ac 0.5.1 2024-03-14 17:35:59 +00:00
Ethan Lane c7e064bb6c Fix vulnerabilities with undici and ip
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-14 17:31:53 +00:00
RenovateBot e32105a849 Update dependency dotenv to v16.4.5 (#182)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [dotenv](https://github.com/motdotla/dotenv) | dependencies | minor | [`16.3.2` -> `16.4.5`](https://renovatebot.com/diffs/npm/dotenv/16.3.2/16.4.5) |

---

### Release Notes

<details>
<summary>motdotla/dotenv (dotenv)</summary>

### [`v16.4.5`](https://github.com/motdotla/dotenv/blob/HEAD/CHANGELOG.md#1645-2024-02-19)

[Compare Source](https://github.com/motdotla/dotenv/compare/v16.4.4...v16.4.5)

##### Changed

-   🐞 fix recent regression when using `path` option. return to historical behavior: do not attempt to auto find `.env` if `path` set. (regression was introduced in `16.4.3`) [#&#8203;814](https://github.com/motdotla/dotenv/pull/814)

### [`v16.4.4`](https://github.com/motdotla/dotenv/blob/HEAD/CHANGELOG.md#1644-2024-02-13)

[Compare Source](https://github.com/motdotla/dotenv/compare/v16.4.3...v16.4.4)

##### Changed

-   🐞 Replaced chaining operator `?.` with old school `&&` (fixing node 12 failures) [#&#8203;812](https://github.com/motdotla/dotenv/pull/812)

### [`v16.4.3`](https://github.com/motdotla/dotenv/blob/HEAD/CHANGELOG.md#1643-2024-02-12)

[Compare Source](https://github.com/motdotla/dotenv/compare/v16.4.2...v16.4.3)

##### Changed

-   Fixed processing of multiple files in `options.path` [#&#8203;805](https://github.com/motdotla/dotenv/pull/805)

### [`v16.4.2`](https://github.com/motdotla/dotenv/blob/HEAD/CHANGELOG.md#1642-2024-02-10)

[Compare Source](https://github.com/motdotla/dotenv/compare/v16.4.1...v16.4.2)

##### Changed

-   Changed funding link in package.json to [`dotenvx.com`](https://dotenvx.com)

### [`v16.4.1`](https://github.com/motdotla/dotenv/blob/HEAD/CHANGELOG.md#1641-2024-01-24)

[Compare Source](https://github.com/motdotla/dotenv/compare/v16.4.0...v16.4.1)

-   Patch support for array as `path` option [#&#8203;797](https://github.com/motdotla/dotenv/pull/797)

### [`v16.4.0`](https://github.com/motdotla/dotenv/blob/HEAD/CHANGELOG.md#1640-2024-01-23)

[Compare Source](https://github.com/motdotla/dotenv/compare/v16.3.2...v16.4.0)

-   Add `error.code` to error messages around `.env.vault` decryption handling [#&#8203;795](https://github.com/motdotla/dotenv/pull/795)
-   Add ability to find `.env.vault` file when filename(s) passed as an array [#&#8203;784](https://github.com/motdotla/dotenv/pull/784)

</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: https://gitea.vylpes.xyz/External/card-drop/pulls/182
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-03-11 19:54:37 +00:00
RenovateBot 2d2c76a266 Update dependency @types/node to v20.11.25 (#181)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
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.11.24` -> `20.11.25`](https://renovatebot.com/diffs/npm/@types%2fnode/20.11.24/20.11.25) |

---

### 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: https://gitea.vylpes.xyz/External/card-drop/pulls/181
Reviewed-by: Vylpes <ethan@vylpes.com>
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-03-11 19:48:03 +00:00
RenovateBot 2377397a2e Update dependency express to v4.18.3 (#180)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [express](http://expressjs.com/) ([source](https://github.com/expressjs/express)) | dependencies | patch | [`4.18.2` -> `4.18.3`](https://renovatebot.com/diffs/npm/express/4.18.2/4.18.3) |

---

### Release Notes

<details>
<summary>expressjs/express (express)</summary>

### [`v4.18.3`](https://github.com/expressjs/express/blob/HEAD/History.md#4183--2024-02-26)

[Compare Source](https://github.com/expressjs/express/compare/4.18.2...4.18.3)

\==========

-   Fix routing requests without method
-   deps: body-parser@1.20.2
    -   Fix strict json error message on Node.js 19+
    -   deps: content-type@~1.0.5
    -   deps: raw-body@2.5.2

</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: https://gitea.vylpes.xyz/External/card-drop/pulls/180
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-03-05 18:39:23 +00:00
RenovateBot 0c94c5817f Update dependency @types/node to v20.11.24 (#179)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
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.11.20` -> `20.11.24`](https://renovatebot.com/diffs/npm/@types%2fnode/20.11.20/20.11.24) |

---

### 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: https://gitea.vylpes.xyz/External/card-drop/pulls/179
Reviewed-by: Vylpes <ethan@vylpes.com>
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-03-05 18:38:18 +00:00
Ethan Lane 42883c3a99 Fix give command using the wrong username (#178)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
# 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 the give command incorrectly using the username of the user who used the command instead of the user who it was actually given to

#174

## 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: https://gitea.vylpes.xyz/External/card-drop/pulls/178
Reviewed-by: VylpesTester <tester@vylpes.com>
Co-authored-by: Ethan Lane <ethan@vylpes.com>
Co-committed-by: Ethan Lane <ethan@vylpes.com>
2024-03-01 20:03:34 +00:00
Ethan Lane 2f9d80f430 Fix trade command (#177)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
# 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 the decline button not working for the initiating user
- Update labels on embed to follow "I Receive" and "You Receive"

#165

## 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: https://gitea.vylpes.xyz/External/card-drop/pulls/177
Reviewed-by: VylpesTester <tester@vylpes.com>
Co-authored-by: Ethan Lane <ethan@vylpes.com>
Co-committed-by: Ethan Lane <ethan@vylpes.com>
2024-03-01 20:02:11 +00:00
RenovateBot 806dcb9ab3 Update dependency @typescript-eslint/parser to v6.21.0 (#176)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint) | devDependencies | minor | [`6.16.0` -> `6.21.0`](https://renovatebot.com/diffs/npm/@typescript-eslint%2fparser/6.16.0/6.21.0) |

---

### Release Notes

<details>
<summary>typescript-eslint/typescript-eslint (@&#8203;typescript-eslint/parser)</summary>

### [`v6.21.0`](https://github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/parser/CHANGELOG.md#6210-2024-02-05)

[Compare Source](https://github.com/typescript-eslint/typescript-eslint/compare/v6.20.0...v6.21.0)

##### 🚀 Features

-   allow `parserOptions.project: false`

##### ❤️  Thank You

-   auvred
-   Brad Zacher
-   Kirk Waiblinger
-   Pete Gonzalez
-   YeonJuan

You can read about our [versioning strategy](https://main--typescript-eslint.netlify.app/users/versioning) and [releases](https://main--typescript-eslint.netlify.app/users/releases) on our website.

### [`v6.20.0`](https://github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/parser/CHANGELOG.md#6200-2024-01-29)

[Compare Source](https://github.com/typescript-eslint/typescript-eslint/compare/v6.19.1...v6.20.0)

This was a version bump only for parser to align it with other projects, there were no code changes.

You can read about our [versioning strategy](https://main--typescript-eslint.netlify.app/users/versioning) and [releases](https://main--typescript-eslint.netlify.app/users/releases) on our website.

### [`v6.19.1`](https://github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/parser/CHANGELOG.md#6191-2024-01-22)

[Compare Source](https://github.com/typescript-eslint/typescript-eslint/compare/v6.19.0...v6.19.1)

This was a version bump only for parser to align it with other projects, there were no code changes.

You can read about our [versioning strategy](https://main--typescript-eslint.netlify.app/users/versioning) and [releases](https://main--typescript-eslint.netlify.app/users/releases) on our website.

### [`v6.19.0`](https://github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/parser/CHANGELOG.md#6190-2024-01-15)

[Compare Source](https://github.com/typescript-eslint/typescript-eslint/compare/v6.18.1...v6.19.0)

This was a version bump only for parser to align it with other projects, there were no code changes.

You can read about our [versioning strategy](https://main--typescript-eslint.netlify.app/users/versioning) and [releases](https://main--typescript-eslint.netlify.app/users/releases) on our website.

### [`v6.18.1`](https://github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/parser/CHANGELOG.md#6181-2024-01-08)

[Compare Source](https://github.com/typescript-eslint/typescript-eslint/compare/v6.18.0...v6.18.1)

This was a version bump only for parser to align it with other projects, there were no code changes.

You can read about our [versioning strategy](https://main--typescript-eslint.netlify.app/users/versioning) and [releases](https://main--typescript-eslint.netlify.app/users/releases) on our website.

### [`v6.18.0`](https://github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/parser/CHANGELOG.md#6180-2024-01-06)

[Compare Source](https://github.com/typescript-eslint/typescript-eslint/compare/v6.17.0...v6.18.0)

This was a version bump only for parser to align it with other projects, there were no code changes.

You can read about our [versioning strategy](https://main--typescript-eslint.netlify.app/users/versioning) and [releases](https://main--typescript-eslint.netlify.app/users/releases) on our website.

### [`v6.17.0`](https://github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/parser/CHANGELOG.md#6170-2024-01-01)

[Compare Source](https://github.com/typescript-eslint/typescript-eslint/compare/v6.16.0...v6.17.0)

**Note:** Version bump only for package [@&#8203;typescript-eslint/parser](https://github.com/typescript-eslint/parser)

You can read about our [versioning strategy](https://main--typescript-eslint.netlify.app/users/versioning) and [releases](https://main--typescript-eslint.netlify.app/users/releases) on our website.

</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: https://gitea.vylpes.xyz/External/card-drop/pulls/176
Reviewed-by: Vylpes <ethan@vylpes.com>
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-02-27 18:33:36 +00:00
RenovateBot 4ceefe20f9 Update dependency @types/node to v20.11.20 (#175)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
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.11.19` -> `20.11.20`](https://renovatebot.com/diffs/npm/@types%2fnode/20.11.19/20.11.20) |

---

### 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: https://gitea.vylpes.xyz/External/card-drop/pulls/175
Reviewed-by: Vylpes <ethan@vylpes.com>
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-02-27 18:32:36 +00:00
Ethan Lane cd2abf0315 Add try/catch to command execution (#173)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
# 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.

- Add try/catch around command execution to console log to stderr and reply in case a command breaks

#67

## 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: https://gitea.vylpes.xyz/External/card-drop/pulls/173
Reviewed-by: VylpesTester <tester@vylpes.com>
Co-authored-by: Ethan Lane <ethan@vylpes.com>
Co-committed-by: Ethan Lane <ethan@vylpes.com>
2024-02-23 18:39:36 +00:00
Ethan Lane 3e09cf7f43 Add trade command (#172)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
# 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.

- Add trade command to the bot, as well as its corresponding button events
- Only the target user can accept
- Both the target user and initiating user can decline, no one else can
- Auto expires after 15 minutes

#165

## 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: https://gitea.vylpes.xyz/External/card-drop/pulls/172
Reviewed-by: VylpesTester <tester@vylpes.com>
Co-authored-by: Ethan Lane <ethan@vylpes.com>
Co-committed-by: Ethan Lane <ethan@vylpes.com>
2024-02-23 18:37:48 +00:00
RenovateBot 9a278b3dc1 Update dependency @typescript-eslint/eslint-plugin to v6.21.0 (#168)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint) | devDependencies | minor | [`6.18.1` -> `6.21.0`](https://renovatebot.com/diffs/npm/@typescript-eslint%2feslint-plugin/6.18.1/6.21.0) |

---

### Release Notes

<details>
<summary>typescript-eslint/typescript-eslint (@&#8203;typescript-eslint/eslint-plugin)</summary>

### [`v6.21.0`](https://github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#6210-2024-02-05)

[Compare Source](https://github.com/typescript-eslint/typescript-eslint/compare/v6.20.0...v6.21.0)

##### 🚀 Features

-   export plugin metadata

-   allow `parserOptions.project: false`

-   **eslint-plugin:** add rule prefer-find

##### 🩹 Fixes

-   **eslint-plugin:** \[no-unused-vars] don't report on types referenced in export assignment expression

-   **eslint-plugin:** \[switch-exhaustiveness-check] better support for intersections, infinite types, non-union values

-   **eslint-plugin:** \[consistent-type-imports] dont report on types used in export assignment expressions

-   **eslint-plugin:** \[no-unnecessary-condition] handle left-hand optional with exactOptionalPropertyTypes option

-   **eslint-plugin:** \[class-literal-property-style] allow getter when same key setter exists

-   **eslint-plugin:** \[no-unnecessary-type-assertion] provide valid fixes for assertions with extra tokens before `as` keyword

##### ❤️  Thank You

-   auvred
-   Brad Zacher
-   Kirk Waiblinger
-   Pete Gonzalez
-   YeonJuan

You can read about our [versioning strategy](https://main--typescript-eslint.netlify.app/users/versioning) and [releases](https://main--typescript-eslint.netlify.app/users/releases) on our website.

### [`v6.20.0`](https://github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#6200-2024-01-29)

[Compare Source](https://github.com/typescript-eslint/typescript-eslint/compare/v6.19.1...v6.20.0)

##### 🚀 Features

-   **eslint-plugin:** \[member-ordering] allow easy reuse of the default ordering

##### 🩹 Fixes

-   **eslint-plugin:** \[no-useless-template-literals] incorrect bigint autofix result

-   **eslint-plugin:** \[prefer-nullish-coalescing] treat any/unknown as non-nullable

-   **eslint-plugin:** \[no-useless-template-literals] report Infinity & NaN

-   **eslint-plugin:** \[prefer-readonly] disable checking accessors

##### ❤️  Thank You

-   Alex Parloti
-   auvred
-   James Browning
-   StyleShit
-   YeonJuan

You can read about our [versioning strategy](https://main--typescript-eslint.netlify.app/users/versioning) and [releases](https://main--typescript-eslint.netlify.app/users/releases) on our website.

### [`v6.19.1`](https://github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#6191-2024-01-22)

[Compare Source](https://github.com/typescript-eslint/typescript-eslint/compare/v6.19.0...v6.19.1)

##### 🩹 Fixes

-   **type-utils:** preventing isUnsafeAssignment infinite recursive calls

-   **eslint-plugin:** \[no-unnecessary-condition] fix false positive for type variable

##### ❤️  Thank You

-   YeonJuan

You can read about our [versioning strategy](https://main--typescript-eslint.netlify.app/users/versioning) and [releases](https://main--typescript-eslint.netlify.app/users/releases) on our website.

### [`v6.19.0`](https://github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#6190-2024-01-15)

[Compare Source](https://github.com/typescript-eslint/typescript-eslint/compare/v6.18.1...v6.19.0)

##### 🚀 Features

-   **eslint-plugin:** \[prefer-promise-reject-errors] add rule

-   **eslint-plugin:** \[no-array-delete] add new rule

-   **eslint-plugin:** \[no-useless-template-literals] add fix suggestions

##### 🩹 Fixes

-   **eslint-plugin:** \[no-unnecessary-type-assertion] detect unnecessary non-null-assertion on a call expression

-   **eslint-plugin:** \[no-unnecesary-type-assertion] treat unknown/any as nullable

##### ❤️  Thank You

-   auvred
-   Brad Zacher
-   Josh Goldberg 
-   Joshua Chen
-   LJX
-   Steven
-   StyleShit

You can read about our [versioning strategy](https://main--typescript-eslint.netlify.app/users/versioning) and [releases](https://main--typescript-eslint.netlify.app/users/releases) on our website.

</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: https://gitea.vylpes.xyz/External/card-drop/pulls/168
Reviewed-by: Vylpes <ethan@vylpes.com>
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-02-19 15:11:33 +00:00
RenovateBot 756f536370 Update dependency @types/node to v20.11.19 (#167)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
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.11.17` -> `20.11.19`](https://renovatebot.com/diffs/npm/@types%2fnode/20.11.17/20.11.19) |

---

### 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: https://gitea.vylpes.xyz/External/card-drop/pulls/167
Reviewed-by: Vylpes <ethan@vylpes.com>
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-02-19 15:10:19 +00:00
Ethan Lane 70d1589584 0.5.0
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-17 17:52:34 +00:00
Ethan Lane 6ee8db6232 Add ability to view another's inventory (#155)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
# 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.

- Add ability to view another user's inventory
- Fix bug where the inventory generation logic was overriding the main array

#131, #138

## Type of change

Please delete options that are not relevant.

- [x] Bug fix (non-breaking change which fixes an issue)
- [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: https://gitea.vylpes.xyz/External/card-drop/pulls/155
Reviewed-by: VylpesTester <tester@vylpes.com>
Co-authored-by: Ethan Lane <ethan@vylpes.com>
Co-committed-by: Ethan Lane <ethan@vylpes.com>
2024-02-16 17:21:50 +00:00
RenovateBot 4c97d41495 Update dependency typeorm to v0.3.20 (#162)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [typeorm](https://typeorm.io) ([source](https://github.com/typeorm/typeorm)) | dependencies | patch | [`0.3.19` -> `0.3.20`](https://renovatebot.com/diffs/npm/typeorm/0.3.19/0.3.20) |

---

### Release Notes

<details>
<summary>typeorm/typeorm (typeorm)</summary>

### [`v0.3.20`](https://github.com/typeorm/typeorm/blob/HEAD/CHANGELOG.md#0320-2024-01-26)

[Compare Source](https://github.com/typeorm/typeorm/compare/0.3.19...0.3.20)

##### Bug Fixes

-   added missing parentheses in where conditions ([#&#8203;10650](https://github.com/typeorm/typeorm/issues/10650)) ([4624930](46249303be)), closes [#&#8203;10534](https://github.com/typeorm/typeorm/issues/10534)
-   don't escape indexPredicate ([#&#8203;10618](https://github.com/typeorm/typeorm/issues/10618)) ([dd49a25](dd49a254dc))
-   fallback runMigrations transaction to DataSourceOptions ([#&#8203;10601](https://github.com/typeorm/typeorm/issues/10601)) ([0cab0dd](0cab0dd730))
-   hangup when load relations with relationLoadStrategy: query ([#&#8203;10630](https://github.com/typeorm/typeorm/issues/10630)) ([54d8d9e](54d8d9efe9)), closes [#&#8203;10481](https://github.com/typeorm/typeorm/issues/10481)
-   include asExpression columns in returning clause ([#&#8203;10632](https://github.com/typeorm/typeorm/issues/10632)) ([f232ba7](f232ba7808)), closes [#&#8203;8450](https://github.com/typeorm/typeorm/issues/8450) [#&#8203;8450](https://github.com/typeorm/typeorm/issues/8450)
-   multiple insert in SAP Hana ([#&#8203;10597](https://github.com/typeorm/typeorm/issues/10597)) ([1b34c9a](1b34c9a49e))
-   resolve issue CREATE/DROP Index concurrently ([#&#8203;10634](https://github.com/typeorm/typeorm/issues/10634)) ([8aa8690](8aa8690f94)), closes [#&#8203;10626](https://github.com/typeorm/typeorm/issues/10626)
-   type inferencing of EntityManager#create ([#&#8203;10569](https://github.com/typeorm/typeorm/issues/10569)) ([99d8249](99d8249e45))

##### Features

-   add json type support for Oracle ([#&#8203;10611](https://github.com/typeorm/typeorm/issues/10611)) ([7e85460](7e85460f10))
-   add postgres multirange column types ([#&#8203;10627](https://github.com/typeorm/typeorm/issues/10627)) ([d0b7670](d0b76703cc)), closes [#&#8203;10556](https://github.com/typeorm/typeorm/issues/10556)
-   add table comment for postgres ([#&#8203;10613](https://github.com/typeorm/typeorm/issues/10613)) ([4493db4](4493db4d1b))

##### Reverts

-   Revert "fix: prevent using absolute table path in migrations unless required ([#&#8203;10123](https://github.com/typeorm/typeorm/issues/10123))" ([#&#8203;10624](https://github.com/typeorm/typeorm/issues/10624)) ([8f371f2](8f371f2397)), closes [#&#8203;10123](https://github.com/typeorm/typeorm/issues/10123) [#&#8203;10624](https://github.com/typeorm/typeorm/issues/10624)
-   revert "feat: nullable embedded entities ([#&#8203;10289](https://github.com/typeorm/typeorm/issues/10289))" ([#&#8203;10614](https://github.com/typeorm/typeorm/issues/10614)) ([15de46f](15de46fd5d)), closes [#&#8203;10289](https://github.com/typeorm/typeorm/issues/10289) [#&#8203;10614](https://github.com/typeorm/typeorm/issues/10614)

</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: https://gitea.vylpes.xyz/External/card-drop/pulls/162
Reviewed-by: Vylpes <ethan@vylpes.com>
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-02-12 18:00:03 +00:00
RenovateBot 96b97b30e6 Update dependency ts-jest to v29.1.2 (#161)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
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.1` -> `29.1.2`](https://renovatebot.com/diffs/npm/ts-jest/29.1.1/29.1.2) |

---

### Release Notes

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

### [`v29.1.2`](https://github.com/kulshekhar/ts-jest/blob/HEAD/CHANGELOG.md#2912-2024-01-22)

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

##### Bug Fixes

-   calculated cache key based on `supportsStaticESM` ([a5d6f2d](a5d6f2d4f4))
-   correct error handling in `processAsync` ([e7be4bf](e7be4bf6a8)), closes [#&#8203;4207](https://github.com/kulshekhar/ts-jest/issues/4207)
-   use `Config.ProjectConfig` ([918312b](918312bee2)), closes [#&#8203;4028](https://github.com/kulshekhar/ts-jest/issues/4028)

</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: https://gitea.vylpes.xyz/External/card-drop/pulls/161
Reviewed-by: Vylpes <ethan@vylpes.com>
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-02-12 17:59:01 +00:00
RenovateBot bc4a870305 Update dependency @types/node to v20.11.17 (#158)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
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.11.10` -> `20.11.17`](https://renovatebot.com/diffs/npm/@types%2fnode/20.11.10/20.11.17) |

---

### 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: https://gitea.vylpes.xyz/External/card-drop/pulls/158
Reviewed-by: Vylpes <ethan@vylpes.com>
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-02-12 17:58:11 +00:00
RenovateBot 935629d831 Update dependency @types/jest to v29.5.12 (#157)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [@types/jest](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/jest) ([source](https://github.com/DefinitelyTyped/DefinitelyTyped)) | dependencies | patch | [`29.5.11` -> `29.5.12`](https://renovatebot.com/diffs/npm/@types%2fjest/29.5.11/29.5.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: https://gitea.vylpes.xyz/External/card-drop/pulls/157
Reviewed-by: Vylpes <ethan@vylpes.com>
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-02-12 17:56:35 +00:00
Ethan Lane a0ba8d7994 Update footer text in CardDropHelperMetadata to include card number (#159)
All checks were successful
ci/woodpecker/manual/woodpecker Pipeline was successful
# 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 footer text in CardDropHelperMetadata to include card number

#127

## 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.

- This has been tested by running the `/drop`, `/dropnumber` commands, and `Reroll` button event. All display the card number on the footer now

# 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: https://gitea.vylpes.xyz/External/card-drop/pulls/159
Reviewed-by: VylpesTester <tester@vylpes.com>
Co-authored-by: Ethan Lane <ethan@vylpes.com>
Co-committed-by: Ethan Lane <ethan@vylpes.com>
2024-02-12 17:49:51 +00:00
Ethan Lane f181c5dbfe Add view command (#153)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
# 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.

- Add view command to let users see specific cards but not claim them

#80

## 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: https://gitea.vylpes.xyz/External/card-drop/pulls/153
Reviewed-by: VylpesTester <tester@vylpes.com>
Co-authored-by: Ethan Lane <ethan@vylpes.com>
Co-committed-by: Ethan Lane <ethan@vylpes.com>
2024-02-02 21:53:42 +00:00
RenovateBot 36ec25113e Update dependency @types/uuid to v9.0.8 (#152)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [@types/uuid](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/uuid) ([source](https://github.com/DefinitelyTyped/DefinitelyTyped)) | dependencies | patch | [`9.0.7` -> `9.0.8`](https://renovatebot.com/diffs/npm/@types%2fuuid/9.0.7/9.0.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: https://gitea.vylpes.xyz/External/card-drop/pulls/152
Reviewed-by: Vylpes <ethan@vylpes.com>
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-01-29 18:10:25 +00:00
RenovateBot f47882c039 Update dependency @types/node to v20.11.10 (#151)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
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.11.5` -> `20.11.10`](https://renovatebot.com/diffs/npm/@types%2fnode/20.11.5/20.11.10) |

---

### 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: https://gitea.vylpes.xyz/External/card-drop/pulls/151
Reviewed-by: Vylpes <ethan@vylpes.com>
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-01-29 18:09:02 +00:00
Ethan Lane 93d11c02a6 Migrate to woodpecker (#150)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
# 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.

- Migrate to Woodpecker CI

> **NOTE:** This will require the Drone project to be disabled before merge!

#122

## 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: https://gitea.vylpes.xyz/External/card-drop/pulls/150
Reviewed-by: VylpesTester <tester@vylpes.com>
Co-authored-by: Ethan Lane <ethan@vylpes.com>
Co-committed-by: Ethan Lane <ethan@vylpes.com>
2024-01-26 21:02:17 +00:00
RenovateBot b21483c13e Update dependency dotenv to v16.3.2 (#149)
All checks were successful
continuous-integration/drone/push Build is passing
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [dotenv](https://github.com/motdotla/dotenv) | dependencies | patch | [`16.3.1` -> `16.3.2`](https://renovatebot.com/diffs/npm/dotenv/16.3.1/16.3.2) |

---

### Release Notes

<details>
<summary>motdotla/dotenv (dotenv)</summary>

### [`v16.3.2`](https://github.com/motdotla/dotenv/blob/HEAD/CHANGELOG.md#1632-2024-01-18)

[Compare Source](https://github.com/motdotla/dotenv/compare/v16.3.1...v16.3.2)

##### Added

-   Add debug message when no encoding set [#&#8203;735](https://github.com/motdotla/dotenv/pull/735)

##### Changed

-   Fix output typing for `populate` [#&#8203;792](https://github.com/motdotla/dotenv/pull/792)
-   Use subarray instead of slice [#&#8203;793](https://github.com/motdotla/dotenv/pull/793)

</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: https://gitea.vylpes.xyz/External/card-drop/pulls/149
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-01-22 17:28:32 +00:00
RenovateBot d6b56664ad Update dependency @types/node to v20.11.5 (#148)
All checks were successful
continuous-integration/drone/push Build is passing
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.11.0` -> `20.11.5`](https://renovatebot.com/diffs/npm/@types%2fnode/20.11.0/20.11.5) |

---

### 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: https://gitea.vylpes.xyz/External/card-drop/pulls/148
Reviewed-by: Vylpes <ethan@vylpes.com>
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-01-22 17:27:17 +00:00
Ethan Lane 38ac26b793 Merge branch 'main' into develop
All checks were successful
continuous-integration/drone/push Build is passing
2024-01-21 15:02:00 +00:00
Ethan Lane 6c00594085 0.4.2 2024-01-21 14:16:23 +00:00
Ethan Lane 25b64df8e9 0.4.2 2024-01-21 14:16:04 +00:00
Ethan Lane 88339d0a43 Update claim event to defer the reply
All checks were successful
continuous-integration/drone/push Build is passing
2024-01-21 14:13:41 +00:00
Ethan Lane 891e013e37 Move defer reply on reroll command 2024-01-21 13:40:06 +00:00
Ethan Lane 7febc06f1e Merge branch 'main' into develop
All checks were successful
continuous-integration/drone/push Build is passing
2024-01-20 15:50:03 +00:00
Ethan Lane 10806bd0f1 0.4.1 2024-01-20 15:46:18 +00:00
Ethan Lane 1c47e605e1 0.4.1 2024-01-20 15:45:53 +00:00
Ethan Lane 67b15a5c7a Fix drop command not replying to the user on image read failure
All checks were successful
continuous-integration/drone/push Build is passing
2024-01-20 15:43:13 +00:00
Ethan Lane de08fa26d7 Update gdrivesync to show an error message of what failed (#144)
All checks were successful
continuous-integration/drone/push Build is passing
# 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.

Fixes # (issue)

## Type of change

Please delete options that are not relevant.

- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] This change requires a documentation update

# 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: https://gitea.vylpes.xyz/External/card-drop/pulls/144
Co-authored-by: Ethan Lane <ethan@vylpes.com>
Co-committed-by: Ethan Lane <ethan@vylpes.com>
2024-01-20 14:31:07 +00:00
Ethan Lane 275a804e28 Update gdrivesync command to error if JSON parsing fails (#143)
All checks were successful
continuous-integration/drone/push Build is passing
# 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 gdrivesync command so if the JSON parse function fails, it returns an error message

#134

## 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: https://gitea.vylpes.xyz/External/card-drop/pulls/143
Reviewed-by: VylpesTester <tester@vylpes.com>
Co-authored-by: Ethan Lane <ethan@vylpes.com>
Co-committed-by: Ethan Lane <ethan@vylpes.com>
2024-01-19 18:05:46 +00:00
RenovateBot cfff3be143 Update dependency @typescript-eslint/eslint-plugin to v6.18.1 (#140)
All checks were successful
continuous-integration/drone/push Build is passing
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint) | devDependencies | minor | [`6.16.0` -> `6.18.1`](https://renovatebot.com/diffs/npm/@typescript-eslint%2feslint-plugin/6.16.0/6.18.1) |

---

### Release Notes

<details>
<summary>typescript-eslint/typescript-eslint (@&#8203;typescript-eslint/eslint-plugin)</summary>

### [`v6.18.1`](https://github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#6181-2024-01-08)

[Compare Source](https://github.com/typescript-eslint/typescript-eslint/compare/v6.18.0...v6.18.1)

##### 🩹 Fixes

-   **eslint-plugin:** \[no-non-null-assertion] provide valid fix when member access is on next line

-   **eslint-plugin:** \[no-unnecessary-condition] improve checking optional callee

-   **eslint-plugin:** \[prefer-readonly] support modifiers of unions and intersections

-   **eslint-plugin:** \[switch-exhaustiveness-check] fix new allowDefaultCaseForExhaustiveSwitch option

##### ❤️  Thank You

-   auvred
-   James
-   Josh Goldberg 
-   YeonJuan

You can read about our [versioning strategy](https://main--typescript-eslint.netlify.app/users/versioning) and [releases](https://main--typescript-eslint.netlify.app/users/releases) on our website.

### [`v6.18.0`](https://github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#6180-2024-01-06)

[Compare Source](https://github.com/typescript-eslint/typescript-eslint/compare/v6.17.0...v6.18.0)

##### 🚀 Features

-   **typescript-estree:** throw on invalid update expressions

-   **eslint-plugin:** \[no-var-requires, no-require-imports] allow option

##### ❤️  Thank You

-   auvred
-   Joshua Chen

You can read about our [versioning strategy](https://main--typescript-eslint.netlify.app/users/versioning) and [releases](https://main--typescript-eslint.netlify.app/users/releases) on our website.

### [`v6.17.0`](https://github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#6170-2024-01-01)

[Compare Source](https://github.com/typescript-eslint/typescript-eslint/compare/v6.16.0...v6.17.0)

##### Bug Fixes

-   **eslint-plugin:** \[no-restricted-imports] prevent crash when `patterns` or `paths` in options are empty ([#&#8203;8108](https://github.com/typescript-eslint/typescript-eslint/issues/8108)) ([675e987](675e987ca1))

##### Features

-   **eslint-plugin:** \[no-floating-promises] flag result of .map(async) ([#&#8203;7897](https://github.com/typescript-eslint/typescript-eslint/issues/7897)) ([5857356](5857356962))
-   **eslint-plugin:** \[switch-exhaustiveness-check] add an option to warn against a `default` case on an already exhaustive `switch` ([#&#8203;7539](https://github.com/typescript-eslint/typescript-eslint/issues/7539)) ([6a219bd](6a219bdfe6))

You can read about our [versioning strategy](https://main--typescript-eslint.netlify.app/users/versioning) and [releases](https://main--typescript-eslint.netlify.app/users/releases) on our website.

</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: https://gitea.vylpes.xyz/External/card-drop/pulls/140
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-01-16 19:18:42 +00:00
RenovateBot 2eb7d698fe Update dependency @types/node to v20.11.0 (#139)
All checks were successful
continuous-integration/drone/push Build is passing
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 | minor | [`20.10.7` -> `20.11.0`](https://renovatebot.com/diffs/npm/@types%2fnode/20.10.7/20.11.0) |

---

### 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: https://gitea.vylpes.xyz/External/card-drop/pulls/139
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-01-16 19:17:45 +00:00
Ethan Lane 486826470a 0.4.0
All checks were successful
continuous-integration/drone/push Build is passing
2024-01-13 13:35:14 +00:00
Ethan Lane 7a52ebb182 Add give command (#137)
All checks were successful
continuous-integration/drone/push Build is passing
# 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.

- Add give command
- Update the whitelist for gdrive sync list to a general admins list

#113

## 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: https://gitea.vylpes.xyz/External/card-drop/pulls/137
Reviewed-by: VylpesTester <tester@vylpes.com>
Co-authored-by: Ethan Lane <ethan@vylpes.com>
Co-committed-by: Ethan Lane <ethan@vylpes.com>
2024-01-12 17:51:29 +00:00
RenovateBot 8a236d01b5 Update dependency typeorm to v0.3.19 (#136)
All checks were successful
continuous-integration/drone/push Build is passing
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [typeorm](https://typeorm.io) ([source](https://github.com/typeorm/typeorm)) | dependencies | patch | [`0.3.17` -> `0.3.19`](https://renovatebot.com/diffs/npm/typeorm/0.3.17/0.3.19) |

---

### Release Notes

<details>
<summary>typeorm/typeorm (typeorm)</summary>

### [`v0.3.19`](https://github.com/typeorm/typeorm/blob/HEAD/CHANGELOG.md#0319-2024-01-03)

[Compare Source](https://github.com/typeorm/typeorm/compare/0.3.18...0.3.19)

##### Bug Fixes

-   fixed `Cannot read properties of undefined (reading 'sync')` caused after glob package upgrade

### [`v0.3.18`](https://github.com/typeorm/typeorm/blob/HEAD/CHANGELOG.md#0318-2024-01-03)

[Compare Source](https://github.com/typeorm/typeorm/compare/0.3.17...0.3.18)

##### Bug Fixes

-   add BaseEntity to model-shim ([#&#8203;10503](https://github.com/typeorm/typeorm/issues/10503)) ([3cf938e](3cf938efc0))
-   add error handling for missing join columns ([#&#8203;10525](https://github.com/typeorm/typeorm/issues/10525)) ([122c897](122c897a2f)), closes [#&#8203;7034](https://github.com/typeorm/typeorm/issues/7034)
-   add missing export for View class ([#&#8203;10261](https://github.com/typeorm/typeorm/issues/10261)) ([7adbc9b](7adbc9bdc7))
-   added fail callback while opening the database in Cordova ([#&#8203;10566](https://github.com/typeorm/typeorm/issues/10566)) ([8b4df5b](8b4df5b299))
-   aggregate function throw error when column alias name is set ([#&#8203;10035](https://github.com/typeorm/typeorm/issues/10035)) ([022d2b5](022d2b5f62)), closes [#&#8203;9927](https://github.com/typeorm/typeorm/issues/9927)
-   backport postgres connection error handling to crdb ([#&#8203;10177](https://github.com/typeorm/typeorm/issues/10177)) ([149226d](149226dd67))
-   bump better-sqlite3 version range ([#&#8203;10452](https://github.com/typeorm/typeorm/issues/10452)) ([75ec8f2](75ec8f2032))
-   caching always enabled not caching queries ([#&#8203;10524](https://github.com/typeorm/typeorm/issues/10524)) ([8af533f](8af533f79f))
-   circular dependency breaking node.js 20.6 ([#&#8203;10344](https://github.com/typeorm/typeorm/issues/10344)) ([ba7ad3c](ba7ad3c69b)), closes [#&#8203;10338](https://github.com/typeorm/typeorm/issues/10338)
-   correctly keep query.data from ormOption for commit / rollback subscribers ([#&#8203;10151](https://github.com/typeorm/typeorm/issues/10151)) ([73ee70b](73ee70b331))
-   default value in child table/entity column decorator for multiple table inheritance is ignored for inherited columns ([#&#8203;10563](https://github.com/typeorm/typeorm/issues/10563)) ([#&#8203;10564](https://github.com/typeorm/typeorm/issues/10564)) ([af77a5d](af77a5d0ac))
-   deletedAt column leaking as side effect of object update while creating a row ([#&#8203;10435](https://github.com/typeorm/typeorm/issues/10435)) ([7de4890](7de4890265))
-   empty objects being hydrated when eager loading relations that have a `@VirtualColumn` ([#&#8203;10432](https://github.com/typeorm/typeorm/issues/10432)) ([b53e410](b53e410e5a)), closes [#&#8203;10431](https://github.com/typeorm/typeorm/issues/10431)
-   extend GiST index with range types for Postgres driver ([#&#8203;10572](https://github.com/typeorm/typeorm/issues/10572)) ([a4900ae](a4900ae15f)), closes [#&#8203;10567](https://github.com/typeorm/typeorm/issues/10567)
-   ignore changes for columns with `update: false` in persistence ([#&#8203;10250](https://github.com/typeorm/typeorm/issues/10250)) ([f8fa1fd](f8fa1fd821)), closes [#&#8203;10249](https://github.com/typeorm/typeorm/issues/10249)
-   improve helper for cli for commands missing positionals ([#&#8203;10133](https://github.com/typeorm/typeorm/issues/10133)) ([9f8899f](9f8899f56c))
-   loading datasource unable to process a regular default export ([#&#8203;10184](https://github.com/typeorm/typeorm/issues/10184)) ([201342d](201342d150)), closes [#&#8203;8810](https://github.com/typeorm/typeorm/issues/8810)
-   logMigration has incorrect logging condition ([#&#8203;10323](https://github.com/typeorm/typeorm/issues/10323)) ([d41930f](d41930f0d6)), closes [#&#8203;10322](https://github.com/typeorm/typeorm/issues/10322) [#&#8203;10322](https://github.com/typeorm/typeorm/issues/10322)
-   ManyToMany ER_DUP_ENTRY error ([#&#8203;10343](https://github.com/typeorm/typeorm/issues/10343)) ([e296063](e296063b12)), closes [#&#8203;5704](https://github.com/typeorm/typeorm/issues/5704)
-   migrations on indexed TIMESTAMP WITH TIME ZONE Oracle columns ([#&#8203;10506](https://github.com/typeorm/typeorm/issues/10506)) ([cf37f13](cf37f1370b)), closes [#&#8203;10493](https://github.com/typeorm/typeorm/issues/10493)
-   mongodb - undefined is not constructor ([#&#8203;10559](https://github.com/typeorm/typeorm/issues/10559)) ([ad5bf11](ad5bf11a91))
-   mongodb resolves leaked cursor ([#&#8203;10316](https://github.com/typeorm/typeorm/issues/10316)) ([2dc9624](2dc9624d00)), closes [#&#8203;10315](https://github.com/typeorm/typeorm/issues/10315)
-   mssql datasource testonborrow not affecting anything ([#&#8203;10589](https://github.com/typeorm/typeorm/issues/10589)) ([122b683](122b683840))
-   nested transactions issues ([#&#8203;10210](https://github.com/typeorm/typeorm/issues/10210)) ([25e6ecd](25e6ecdfd2))
-   prevent using absolute table path in migrations unless required ([#&#8203;10123](https://github.com/typeorm/typeorm/issues/10123)) ([dd59524](dd595242a7))
-   remove `date-fns` in favor of `DayJs` ([#&#8203;10306](https://github.com/typeorm/typeorm/issues/10306)) ([cf7147f](cf7147fa7c))
-   remove dynamic require calls ([#&#8203;10196](https://github.com/typeorm/typeorm/issues/10196)) ([a939654](a939654c95))
-   resolve circular dependency when using Vite ([#&#8203;10273](https://github.com/typeorm/typeorm/issues/10273)) ([080528b](080528b117))
-   resolve issue building eager relation alias for nested relations ([#&#8203;10004](https://github.com/typeorm/typeorm/issues/10004)) ([c6f608d](c6f608d3e8)), closes [#&#8203;9944](https://github.com/typeorm/typeorm/issues/9944)
-   resolve issue of generating migration for numeric arrays repeatedly ([#&#8203;10471](https://github.com/typeorm/typeorm/issues/10471)) ([39fdcf6](39fdcf651f)), closes [#&#8203;10043](https://github.com/typeorm/typeorm/issues/10043)
-   resolve issue queryBuilder makes different parameter identifiers for same parameter ([#&#8203;10327](https://github.com/typeorm/typeorm/issues/10327)) ([6c918ea](6c918ea392)), closes [#&#8203;7308](https://github.com/typeorm/typeorm/issues/7308)
-   resolve issues on upsert ([#&#8203;10588](https://github.com/typeorm/typeorm/issues/10588)) ([dc1bfed](dc1bfed6d5)), closes [#&#8203;10587](https://github.com/typeorm/typeorm/issues/10587)
-   scrub all comment end markers from comments ([#&#8203;10163](https://github.com/typeorm/typeorm/issues/10163)) ([d937f61](d937f6106a))
-   serialize bigint when building a query id [#&#8203;10336](https://github.com/typeorm/typeorm/issues/10336) ([#&#8203;10337](https://github.com/typeorm/typeorm/issues/10337)) ([bfc1cc5](bfc1cc5ab4))
-   should automatically cache if alwaysEnable ([#&#8203;10137](https://github.com/typeorm/typeorm/issues/10137)) ([173910e](173910ed79)), closes [#&#8203;9910](https://github.com/typeorm/typeorm/issues/9910)
-   SQLite simple-enum column parsing ([#&#8203;10550](https://github.com/typeorm/typeorm/issues/10550)) ([696e688](696e688d00))
-   update UpdateDateColumn on upsert ([#&#8203;10458](https://github.com/typeorm/typeorm/issues/10458)) ([fdb9866](fdb9866ad2)), closes [#&#8203;9015](https://github.com/typeorm/typeorm/issues/9015)
-   upgrade ts-node version to latest(10.9.1) version ([#&#8203;10143](https://github.com/typeorm/typeorm/issues/10143)) ([fcb9904](fcb9904f24))
-   using async datasource to configure typeorm ([#&#8203;10170](https://github.com/typeorm/typeorm/issues/10170)) ([fbd45db](fbd45dba32))

##### Features

-   ability to change default replication mode ([#&#8203;10419](https://github.com/typeorm/typeorm/issues/10419)) ([72b1d1b](72b1d1b865))
-   add concurrent indexes for postgres ([#&#8203;10442](https://github.com/typeorm/typeorm/issues/10442)) ([f4e6eaf](f4e6eaf155))
-   add exists and exists by ([#&#8203;10291](https://github.com/typeorm/typeorm/issues/10291)) ([b6b46fb](b6b46fb133))
-   add isolated where statements ([#&#8203;10213](https://github.com/typeorm/typeorm/issues/10213)) ([3cda7ec](3cda7ec39d))
-   add MSSQL disableAsciiToUnicodeParamConversion option and tests ([#&#8203;10161](https://github.com/typeorm/typeorm/issues/10161)) ([df7c069](df7c06948c)), closes [#&#8203;10131](https://github.com/typeorm/typeorm/issues/10131)
-   add support for mssql server DefaultAzureCredential usage ([#&#8203;10246](https://github.com/typeorm/typeorm/issues/10246)) ([c8ee5b1](c8ee5b1d1a))
-   add support for table comment in MySQL ([#&#8203;10017](https://github.com/typeorm/typeorm/issues/10017)) ([338df16](338df16439))
-   allow to use custom type witch extends object type for find where argument ([#&#8203;10475](https://github.com/typeorm/typeorm/issues/10475)) ([48f5f85](48f5f85d68))
-   BeforeQuery and AfterQuery events ([#&#8203;10234](https://github.com/typeorm/typeorm/issues/10234)) ([5c28154](5c28154cbe)), closes [#&#8203;3302](https://github.com/typeorm/typeorm/issues/3302)
-   custom STI discriminator value for EntitySchema ([#&#8203;10508](https://github.com/typeorm/typeorm/issues/10508)) ([b240d87](b240d87f34)), closes [#&#8203;10494](https://github.com/typeorm/typeorm/issues/10494)
-   enabled CTE for oracle driver ([#&#8203;10319](https://github.com/typeorm/typeorm/issues/10319)) ([65858f3](65858f3a17))
-   entityId in InsertEvent ([#&#8203;10540](https://github.com/typeorm/typeorm/issues/10540)) ([ae006af](ae006af501))
-   expose countDocuments in mongodb ([#&#8203;10314](https://github.com/typeorm/typeorm/issues/10314)) ([ebd61d1](ebd61d1440))
-   exposed entity and criteria properties on EntityNotFoundError ([#&#8203;10202](https://github.com/typeorm/typeorm/issues/10202)) ([bafcd17](bafcd1709b))
-   implement column comments for SAP HANA ([#&#8203;10502](https://github.com/typeorm/typeorm/issues/10502)) ([45e31cc](45e31cc57a))
-   implement OR operator ([#&#8203;10086](https://github.com/typeorm/typeorm/issues/10086)) ([a00b1df](a00b1df68f)), closes [#&#8203;10054](https://github.com/typeorm/typeorm/issues/10054) [#&#8203;10054](https://github.com/typeorm/typeorm/issues/10054) [#&#8203;10054](https://github.com/typeorm/typeorm/issues/10054) [#&#8203;10054](https://github.com/typeorm/typeorm/issues/10054) [#&#8203;10054](https://github.com/typeorm/typeorm/issues/10054) [#&#8203;10054](https://github.com/typeorm/typeorm/issues/10054) [#&#8203;10054](https://github.com/typeorm/typeorm/issues/10054)
-   implement streaming for SAP HANA ([#&#8203;10512](https://github.com/typeorm/typeorm/issues/10512)) ([7e9cead](7e9cead8a3))
-   implements QueryFailedError generic for driverError typing ([#&#8203;10253](https://github.com/typeorm/typeorm/issues/10253)) ([78b2f48](78b2f4805c))
-   modify repository.extend method for chaining repositories ([#&#8203;10256](https://github.com/typeorm/typeorm/issues/10256)) ([ca29c0f](ca29c0ff8e))
-   nullable embedded entities ([#&#8203;10289](https://github.com/typeorm/typeorm/issues/10289)) ([e67d704](e67d704138))
-   support for MongoDB 6.x ([#&#8203;10545](https://github.com/typeorm/typeorm/issues/10545)) ([3647b26](3647b269cc))
-   support mssql@10 ([#&#8203;10356](https://github.com/typeorm/typeorm/issues/10356)) ([f6bb671](f6bb6711e2)), closes [#&#8203;10340](https://github.com/typeorm/typeorm/issues/10340)
-   use node-oracledb 6 ([#&#8203;10285](https://github.com/typeorm/typeorm/issues/10285)) ([3af891a](3af891a8e6)), closes [#&#8203;10277](https://github.com/typeorm/typeorm/issues/10277)
-   user-defined index name for STI discriminator column ([#&#8203;10509](https://github.com/typeorm/typeorm/issues/10509)) ([89c5257](89c525761d)), closes [#&#8203;10496](https://github.com/typeorm/typeorm/issues/10496)

##### Performance Improvements

-   improve SapQueryRunner performance ([#&#8203;10198](https://github.com/typeorm/typeorm/issues/10198)) ([f6b87e3](f6b87e3ee1))

##### BREAKING CHANGES

-   With node-oracledb the thin client is used as default. Added a option to use the thick client. Also added the option to specify the instant client lib
-   MongoDB: from the previous behavior of returning a result with metadata describing when a document is not found.
    See: https://github.com/mongodb/node-mongodb-native/blob/HEAD/etc/notes/CHANGES\_6.0.0.md
-   [new nullable embeds feature](https://github.com/typeorm/typeorm/pull/10289) introduced a breaking change which might enforce you to update types on your entities to `  | null `,
    if all columns in your embed entity are nullable. Since database queries now return embedded property as `null` if all its column values are null.

</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: https://gitea.vylpes.xyz/External/card-drop/pulls/136
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-01-08 13:43:50 +00:00
RenovateBot be591c14c6 Update dependency @types/node to v20.10.7 (#135)
All checks were successful
continuous-integration/drone/push Build is passing
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.10.6` -> `20.10.7`](https://renovatebot.com/diffs/npm/@types%2fnode/20.10.6/20.10.7) |

---

### 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: https://gitea.vylpes.xyz/External/card-drop/pulls/135
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-01-08 13:43:01 +00:00
RenovateBot 9703d1d2c3 Update dependency typescript to v5.3.3 (#117)
All checks were successful
continuous-integration/drone/push Build is passing
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [typescript](https://www.typescriptlang.org/) ([source](https://github.com/Microsoft/TypeScript)) | devDependencies | minor | [`5.2.2` -> `5.3.3`](https://renovatebot.com/diffs/npm/typescript/5.2.2/5.3.3) |

---

### Release Notes

<details>
<summary>Microsoft/TypeScript (typescript)</summary>

### [`v5.3.3`](https://github.com/microsoft/TypeScript/releases/tag/v5.3.3): TypeScript 5.3.3

[Compare Source](https://github.com/Microsoft/TypeScript/compare/v5.3.2...v5.3.3)

For release notes, check out the [release announcement](https://devblogs.microsoft.com/typescript/announcing-typescript-5-3/).

For the complete list of fixed issues, check out the

-   [fixed issues query for Typescript 5.3.0 (Beta)](https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93\&q=milestone%3A%22TypeScript+5.3.0%22+is%3Aclosed+).
-   [fixed issues query for Typescript 5.3.1 (RC)](https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93\&q=milestone%3A%22TypeScript+5.3.1%22+is%3Aclosed+).
-   [fixed issues query for Typescript 5.3.2 (Stable)](https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93\&q=milestone%3A%22TypeScript+5.3.2%22+is%3Aclosed+).
-   [fixed issues query for Typescript 5.3.3 (Stable)](https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93\&q=milestone%3A%22TypeScript+5.3.3%22+is%3Aclosed+).

Downloads are available on:

-   [NuGet package](https://www.nuget.org/packages/Microsoft.TypeScript.MSBuild)

### [`v5.3.2`](https://github.com/microsoft/TypeScript/releases/tag/v5.3.2): TypeScript 5.3

[Compare Source](https://github.com/Microsoft/TypeScript/compare/v5.2.2...v5.3.2)

For release notes, check out the [release announcement](https://devblogs.microsoft.com/typescript/announcing-typescript-5-3/).

For the complete list of fixed issues, check out the

-   [fixed issues query for Typescript 5.3.0 (Beta)](https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93\&q=milestone%3A%22TypeScript+5.3.0%22+is%3Aclosed+).
-   [fixed issues query for Typescript 5.3.1 (RC)](https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93\&q=milestone%3A%22TypeScript+5.3.1%22+is%3Aclosed+).
-   [fixed issues query for Typescript 5.3.2 (Stable)](https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93\&q=milestone%3A%22TypeScript+5.3.2%22+is%3Aclosed+).

Downloads are available on:

-   [NuGet package](https://www.nuget.org/packages/Microsoft.TypeScript.MSBuild)

</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: https://gitea.vylpes.xyz/External/card-drop/pulls/117
Reviewed-by: Vylpes <ethan@vylpes.com>
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-01-08 13:40:37 +00:00
Ethan Lane 39529cf20c Add ESLint and fix issues (#133)
All checks were successful
continuous-integration/drone/push Build is passing
# 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.

- Add ESLint to the project
- Fix issues which ESLint found

#49

## Type of change

Please delete options that are not relevant.

- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] This change requires a documentation update

# 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: https://gitea.vylpes.xyz/External/card-drop/pulls/133
Reviewed-by: VylpesTester <tester@vylpes.com>
Co-authored-by: Ethan Lane <ethan@vylpes.com>
Co-committed-by: Ethan Lane <ethan@vylpes.com>
2024-01-05 19:26:44 +00:00
RenovateBot 84749c3381 Update dependency @types/node to v20.10.6 (#132)
All checks were successful
continuous-integration/drone/push Build is passing
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.10.5` -> `20.10.6`](https://renovatebot.com/diffs/npm/@types%2fnode/20.10.5/20.10.6) |

---

### 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: https://gitea.vylpes.xyz/External/card-drop/pulls/132
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-01-01 16:09:49 +00:00
Ethan Lane fb874be76a Fix dropnumber and droprarity commands
All checks were successful
continuous-integration/drone/push Build is passing
2023-12-29 22:12:20 +00:00
Ethan Lane e05059cb9b Add to renovate config to add label on PRs (#128)
All checks were successful
continuous-integration/drone/push Build is passing
# 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 renovate config so that the bot will add the `type/dependencies` label to the PRs

#55

## 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: https://gitea.vylpes.xyz/External/card-drop/pulls/128
Reviewed-by: VylpesTester <tester@vylpes.com>
Co-authored-by: Ethan Lane <ethan@vylpes.com>
Co-committed-by: Ethan Lane <ethan@vylpes.com>
2023-12-29 21:03:15 +00:00
Ethan Lane dd86ecd5a4 Use exports in script
All checks were successful
continuous-integration/drone/push Build is passing
2023-12-29 21:00:44 +00:00
Ethan Lane 99f23cfb1c Add source
Some checks failed
continuous-integration/drone/push Build is failing
2023-12-29 20:56:14 +00:00
Ethan Lane ffaf533608 Redoo
Some checks failed
continuous-integration/drone/push Build is failing
2023-12-29 20:54:53 +00:00
Ethan Lane 526b42bb4a Undo commit
Some checks failed
continuous-integration/drone/push Build is failing
2023-12-29 20:41:02 +00:00
Ethan Lane c5d2edf011 Use alpine
Some checks failed
continuous-integration/drone/push Build is failing
2023-12-29 20:34:18 +00:00
Ethan Lane 70457ac850 Use on deploy script too
Some checks failed
continuous-integration/drone/push Build is failing
2023-12-29 20:27:38 +00:00
Ethan Lane bc494970a0 Use ip address
Some checks failed
continuous-integration/drone/push Build is failing
2023-12-29 20:25:15 +00:00
Ethan Lane 736053fb8b Use prescript
Some checks failed
continuous-integration/drone/push Build is failing
2023-12-29 20:24:10 +00:00
Ethan Lane 1ee7bb8630 Update drone script to use rsync (#121)
Some checks failed
continuous-integration/drone/push Build is failing
# 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 drone pipelines to use resync

> **NOTE:** This requires a new repository secret - `ssh_key`

> **NOTE:** This requires moving the cards directory into the new appdata folder

#56

## 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.

- This can only be tested once merged, so no testing has been done, but a check has been done by me as a review

# 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: https://gitea.vylpes.xyz/External/card-drop/pulls/121
Reviewed-by: VylpesTester <tester@vylpes.com>
Co-authored-by: Ethan Lane <ethan@vylpes.com>
Co-committed-by: Ethan Lane <ethan@vylpes.com>
2023-12-29 19:51:59 +00:00
Ethan Lane 5df92554c0 Remove resolution for undici (#126)
All checks were successful
continuous-integration/drone/push Build is passing
# 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.

- Remove resolution for undici, as it is no longer causing a vulnerability

#125

## 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: https://gitea.vylpes.xyz/External/card-drop/pulls/126
Reviewed-by: VylpesTester <tester@vylpes.com>
Co-authored-by: Ethan Lane <ethan@vylpes.com>
Co-committed-by: Ethan Lane <ethan@vylpes.com>
2023-12-29 19:49:11 +00:00
RenovateBot 82941d4909 Update dependency np to v9 (#123)
All checks were successful
continuous-integration/drone/push Build is passing
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [np](https://github.com/sindresorhus/np) | devDependencies | major | [`^8.0.4` -> `^9.0.0`](https://renovatebot.com/diffs/npm/np/8.0.4/9.2.0) |

---

### Release Notes

<details>
<summary>sindresorhus/np (np)</summary>

### [`v9.2.0`](https://github.com/sindresorhus/np/releases/tag/v9.2.0)

[Compare Source](https://github.com/sindresorhus/np/compare/v9.1.0...v9.2.0)

-   Fix yarn npm publish for scoped packages  [`8d3a984`](https://github.com/sindresorhus/np/commit/8d3a984)
-   Fix broken revert code after publish failure  [`819ed29`](https://github.com/sindresorhus/np/commit/819ed29)

### [`v9.1.0`](https://github.com/sindresorhus/np/releases/tag/v9.1.0)

[Compare Source](https://github.com/sindresorhus/np/compare/v9.0.0...v9.1.0)

-   Add Yarn Berry support ([#&#8203;723](https://github.com/sindresorhus/np/issues/723))  [`0d9522b`](https://github.com/sindresorhus/np/commit/0d9522b)

### [`v9.0.0`](https://github.com/sindresorhus/np/releases/tag/v9.0.0)

[Compare Source](https://github.com/sindresorhus/np/compare/v8.0.4...v9.0.0)

##### Breaking

-   Require Node.js 18 and npm 9  [`6c2e00e`](https://github.com/sindresorhus/np/commit/6c2e00e)

##### Improvements

-   Group unpublished files in folders ([#&#8203;716](https://github.com/sindresorhus/np/issues/716))  [`c31c2bc`](https://github.com/sindresorhus/np/commit/c31c2bc)
-   improve messages related to new files and dependencies ([#&#8203;702](https://github.com/sindresorhus/np/issues/702))  [`ad7b09e`](https://github.com/sindresorhus/np/commit/ad7b09e)

</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: https://gitea.vylpes.xyz/External/card-drop/pulls/123
Reviewed-by: Vylpes <ethan@vylpes.com>
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2023-12-25 15:19:44 +00:00
Ethan Lane bcb7beabc6 Create simple inventory list (#120)
All checks were successful
continuous-integration/drone/push Build is passing
# 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 a simple inventory list

#97

## 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: https://gitea.vylpes.xyz/External/card-drop/pulls/120
Reviewed-by: VylpesTester <tester@vylpes.com>
Co-authored-by: Ethan Lane <ethan@vylpes.com>
Co-committed-by: Ethan Lane <ethan@vylpes.com>
2023-12-22 14:41:13 +00:00
RenovateBot 66b499d8d2 Update dependency @types/node to v20.10.5 (#116)
All checks were successful
continuous-integration/drone/push Build is passing
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.10.4` -> `20.10.5`](https://renovatebot.com/diffs/npm/@types%2fnode/20.10.4/20.10.5) |

---

### 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: https://gitea.vylpes.xyz/External/card-drop/pulls/116
Reviewed-by: Vylpes <ethan@vylpes.com>
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2023-12-18 14:38:48 +00:00
Ethan Lane a4abaa6ae4 0.3.1
All checks were successful
continuous-integration/drone/push Build is passing
2023-12-13 17:34:50 +00:00
Ethan Lane 0029e4a456 Update .env version to 0.3.1
All checks were successful
continuous-integration/drone/push Build is passing
2023-12-13 17:33:21 +00:00
Ethan Lane 7a72be4e64 Add console log on drop command error 2023-12-13 17:32:51 +00:00
83 changed files with 8750 additions and 10905 deletions

View file

@ -4,16 +4,36 @@ kind: pipeline
name: deployment
steps:
- name: deploy
image: appleboy/drone-ssh
- name: build
image: node
commands:
- npm ci
- npm run build
- name: test
image: node
commands:
- npm test
- name: deploy to prod
image: drillster/drone-rsync
secrets: [ ssh_key, bot_token_prod ]
settings:
host: 192.168.68.120
username: vylpes
password:
from_secret: ssh_password
port: 22
hosts:
- 192.168.68.120
user: vylpes
key:
from_secret: ssh_key
source: .
target: ~/apps/card-drop/card-drop_prod
recursive: true
script:
- sh /home/vylpes/scripts/card-drop/deploy_prod.sh
- export PATH="$HOME/.yarn/bin:$PATH"
- export PATH="$HOME/.nodeuse/bin:$PATH"
- export BOT_TOKEN="$BOT_TOKEN_PROD"
- cd ~/apps/card-drop/card-drop_prod
- docker compose --file docker-compose.prod.yml up -d
- sleep 10
- cp .prod.env .env
- pm2 restart card-drop_prod || pm2 start --name card-drop_prod dist/bot.js
trigger:
event:
@ -25,16 +45,36 @@ kind: pipeline
name: staging
steps:
- name: stage
image: appleboy/drone-ssh
- name: build
image: node
commands:
- npm ci
- npm run build
- name: test
image: node
commands:
- npm test
- name: deploy to stage
image: drillster/drone-rsync
secrets: [ ssh_key, bot_token_stage ]
settings:
host: 192.168.68.120
username: vylpes
password:
from_secret: ssh_password
port: 22
hosts:
- 192.168.68.120
user: vylpes
key:
from_secret: ssh_key
source: .
target: ~/apps/card-drop/card-drop_stage
recursive: true
script:
- sh /home/vylpes/scripts/card-drop/deploy_stage.sh
- export PATH="$HOME/.yarn/bin:$PATH"
- export PATH="$HOME/.nodeuse/bin:$PATH"
- export BOT_TOKEN="$BOT_TOKEN_STAGE"
- cd ~/apps/card-drop/card-drop_stage
- docker compose --file docker-compose.stage.yml up -d
- sleep 10
- cp .stage.env .env
- pm2 restart card-drop_stage || pm2 start --name card-drop_stage dist/bot.js
trigger:
branch:
@ -54,16 +94,18 @@ steps:
- npm ci
- npm run build
- name: lint
image: node
commands:
- npm run lint
- name: test
image: node
commands:
- npm ci
- npm test
trigger:
branch:
- main
- develop
- hotfix/*
- feature/*
- renovate/*

View file

@ -7,26 +7,30 @@
# any secret values.
BOT_TOKEN=
BOT_VER=0.3.0 DEV
BOT_VER=0.6.4
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=./.temp
DB_HOST=127.0.0.1
DB_PORT=3301
DB_NAME=carddrop
DB_AUTH_USER=dev
DB_AUTH_PASS=dev
DB_SYNC=true
DB_LOGGING=true
DB_AUTH_USER=
DB_AUTH_PASS=
DB_SYNC=
DB_LOGGING=
DB_DATA_LOCATION=./.temp/database
DB_CARD_FILE=:memory:
EXPRESS_PORT=3303
EXPRESS_PORT=3302
GDRIVESYNC_WHITELIST=147392775707426816,887272961504071690
GDRIVESYNC_AUTO=true
GDRIVESYNC_AUTO=true

45
.eslintrc.json Normal file
View file

@ -0,0 +1,45 @@
{
"env": {
"browser": true,
"es2021": true
},
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module"
},
"plugins": [
"@typescript-eslint"
],
"rules": {
"indent": [
"error",
4
],
"linebreak-style": [
"error",
"unix"
],
"quotes": [
"error",
"double"
],
"semi": [
"error",
"always"
]
},
"globals": {
"jest": true,
"require": true,
"exports": true,
"process": true
},
"ignorePatterns": [
"dist/**/*"
]
}

View file

@ -0,0 +1,73 @@
name: Deploy To Production
on:
push:
branches:
- main
jobs:
build:
environment: prod
runs-on: node
steps:
- uses: actions/checkout@v4
- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: 18.x
- run: yarn install --frozen-lockfile
- run: yarn build
- run: yarn test
- run: yarn lint
- name: "Copy files over to location"
run: cp -r . ${{ secrets.PROD_REPO_PATH }}
deploy:
environment: prod
needs: build
runs-on: node
steps:
- uses: https://github.com/appleboy/ssh-action@v1.0.0
env:
DB_NAME: ${{ secrets.PROD_DB_NAME }}
DB_AUTH_USER: ${{ secrets.PROD_DB_AUTH_USER }}
DB_AUTH_PASS: ${{ secrets.PROD_DB_AUTH_PASS }}
DB_HOST: ${{ secrets.PROD_DB_HOST }}
DB_PORT: ${{ secrets.PROD_DB_PORT }}
DB_ROOT_HOST: ${{ secrets.PROD_DB_ROOT_HOST }}
DB_SYNC: ${{ secrets.PROD_DB_SYNC }}
DB_LOGGING: ${{ secrets.PROD_DB_LOGGING }}
DB_DATA_LOCATION: ${{ secrets.PROD_DB_DATA_LOCATION }}
SERVER_PATH: ${{ secrets.PROD_SSH_SERVER_PATH }}
BOT_TOKEN: ${{ secrets.PROD_BOT_TOKEN }}
BOT_VER: ${{ vars.PROD_BOT_VER }}
BOT_AUTHOR: ${{ vars.PROD_BOT_AUTHOR }}
BOT_OWNERID: ${{ vars.PROD_BOT_OWNERID }}
BOT_CLIENTID: ${{ vars.PROD_BOT_CLIENTID }}
BOT_ENV: ${{ vars.PROD_BOT_ENV }}
BOT_ADMINS: ${{ vars.PROD_BOT_ADMINS }}
ABOUT_FUNDING: ${{ vars.PROD_ABOUT_FUNDING }}
ABOUT_REPO: ${{ vars.PROD_ABOUT_REPO }}
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,BOT_LOGLEVEL
script: |
source .sshrc \
&& cd /home/vylpes/apps/card-drop/card-drop_prod \
&& docker compose down \
&& (pm2 stop card-drop_prod || true) \
&& (pm2 delete card-drop_prod || true) \
&& docker compose up -d \
&& sleep 10 \
&& yarn run db:up \
&& pm2 start --name card-drop_prod dist/bot.js

View file

@ -0,0 +1,73 @@
name: Deploy To Stage
on:
push:
branches:
- develop
jobs:
build:
environment: stage
runs-on: node
steps:
- uses: actions/checkout@v4
- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: 18.x
- run: yarn install --frozen-lockfile
- run: yarn build
- run: yarn test
- run: yarn lint
- name: "Copy files over to location"
run: cp -r . ${{ secrets.STAGE_REPO_PATH }}
deploy:
environment: prod
needs: build
runs-on: node
steps:
- uses: https://github.com/appleboy/ssh-action@v1.0.0
env:
DB_NAME: ${{ secrets.STAGE_DB_NAME }}
DB_AUTH_USER: ${{ secrets.STAGE_DB_AUTH_USER }}
DB_AUTH_PASS: ${{ secrets.STAGE_DB_AUTH_PASS }}
DB_HOST: ${{ secrets.STAGE_DB_HOST }}
DB_PORT: ${{ secrets.STAGE_DB_PORT }}
DB_ROOT_HOST: ${{ secrets.STAGE_DB_ROOT_HOST }}
DB_SYNC: ${{ secrets.STAGE_DB_SYNC }}
DB_LOGGING: ${{ secrets.STAGE_DB_LOGGING }}
DB_DATA_LOCATION: ${{ secrets.STAGE_DB_DATA_LOCATION }}
SERVER_PATH: ${{ secrets.STAGE_SSH_SERVER_PATH }}
BOT_TOKEN: ${{ secrets.STAGE_BOT_TOKEN }}
BOT_VER: ${{ vars.STAGE_BOT_VER }}
BOT_AUTHOR: ${{ vars.STAGE_BOT_AUTHOR }}
BOT_OWNERID: ${{ vars.STAGE_BOT_OWNERID }}
BOT_CLIENTID: ${{ vars.STAGE_BOT_CLIENTID }}
BOT_ENV: ${{ vars.STAGE_BOT_ENV }}
BOT_ADMINS: ${{ vars.STAGE_BOT_ADMINS }}
ABOUT_FUNDING: ${{ vars.STAGE_ABOUT_FUNDING }}
ABOUT_REPO: ${{ vars.STAGE_ABOUT_REPO }}
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,BOT_LOGLEVEL
script: |
source .sshrc \
&& cd /home/vylpes/apps/card-drop/card-drop_stage \
&& docker compose down \
&& (pm2 stop card-drop_stage || true) \
&& (pm2 delete card-drop_stage || true) \
&& docker compose up -d \
&& sleep 10 \
&& yarn run db:up \
&& pm2 start --name card-drop_stage dist/bot.js

View file

@ -0,0 +1,25 @@
name: Test
on:
push:
branches:
- feature/*
- hotfix/*
- renovate/*
jobs:
build:
environment: stage
runs-on: node
steps:
- uses: actions/checkout@v4
- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: 18.x
- run: yarn install --frozen-lockfile
- run: yarn build
- run: yarn test
- run: yarn lint

5
.gitignore vendored
View file

@ -107,5 +107,6 @@ config.json
.DS_Store
ormconfig.json
gdrive-credentials.json
cards/
*.db
data/
*.db
.temp/

View file

@ -1,32 +0,0 @@
# Security Warning! Do not commit this file to any VCS!
# This is a local file to speed up development process,
# so you don't have to change your environment variables.
#
# This is not applied to `.env.template`!
# Template files must be committed to the VCS, but must not contain
# any secret values.
BOT_TOKEN=
BOT_VER=0.3.0
BOT_AUTHOR=Vylpes
BOT_OWNERID=147392775707426816
BOT_CLIENTID=1093810443589529631
BOT_ENV=1
ABOUT_FUNDING=
ABOUT_REPO=
DB_HOST=127.0.0.1
DB_PORT=3321
DB_NAME=carddrop
DB_AUTH_USER=prod
DB_AUTH_PASS=prod
DB_SYNC=false
DB_LOGGING=false
DB_CARD_FILE=:memory:
EXPRESS_PORT=3323
GDRIVESYNC_WHITELIST=147392775707426816,887272961504071690
GDRIVESYNC_AUTO=false

View file

@ -1,32 +0,0 @@
# Security Warning! Do not commit this file to any VCS!
# This is a local file to speed up development process,
# so you don't have to change your environment variables.
#
# This is not applied to `.env.template`!
# Template files must be committed to the VCS, but must not contain
# any secret values.
BOT_TOKEN=
BOT_VER=0.3.0 BETA
BOT_AUTHOR=Vylpes
BOT_OWNERID=147392775707426816
BOT_CLIENTID=1147976642942214235
BOT_ENV=2
ABOUT_FUNDING=
ABOUT_REPO=
DB_HOST=127.0.0.1
DB_PORT=3311
DB_NAME=carddrop
DB_AUTH_USER=stage
DB_AUTH_PASS=stage
DB_SYNC=false
DB_LOGGING=false
DB_CARD_FILE=:memory:
EXPRESS_PORT=3313
GDRIVESYNC_WHITELIST=147392775707426816,887272961504071690
GDRIVESYNC_AUTO=false

47
.woodpecker.yml Normal file
View file

@ -0,0 +1,47 @@
steps:
build:
image: node
commands:
- npm ci
- npm run build
when:
event: push
branch: [ hotfix/*, feature/*, renovate/*, develop, main ]
lint:
image: node
commands:
- npm run lint
when:
event: push
branch: [ hotfix/*, feature/*, renovate/*, develop, main ]
test:
image: node
commands:
- npm test
when:
event: push
branch: [ hotfix/*, feature/*, renovate/*, develop, main ]
stage:
image: alpine
secrets: [ ssh_key, stage_bot_token ]
commands:
- apk add rsync openssh-client
- eval `ssh-agent -s`
- echo "$SSH_KEY" | tr -d '\r' | ssh-add -
- rsync -e "ssh -o StrictHostKeyChecking=no" -r ./* vylpes@192.168.1.115:/home/vylpes/apps/card-drop/card-drop_stage
- ssh vylpes@192.168.1.115 BOT_TOKEN='$${stage_bot_token}' 'bash -s' < ./scripts/deploy_stage.sh
when:
event: push
branch: [ develop ]
deploy:
image: alpine
secrets: [ ssh_key, prod_bot_token ]
commands:
- apk add rsync openssh-client
- eval `ssh-agent -s`
- echo "$SSH_KEY" | tr -d '\r' | ssh-add -
- rsync -e "ssh -o StrictHostKeyChecking=no" -r ./* vylpes@192.168.1.115:/home/vylpes/apps/card-drop/card-drop_prod
- ssh vylpes@192.168.1.115 BOT_TOKEN='$${prod_bot_token}' 'bash -s' < ./scripts/deploy_prod.sh
when:
event: push
branch: [ main ]

View file

@ -0,0 +1,7 @@
CREATE TABLE `user` (
`Id` varchar(255) NOT NULL,
`WhenCreated` datetime NOT NULL,
`WhenUpdated` datetime NOT NULL,
`Currency` int NOT NULL,
PRIMARY KEY (`Id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

View file

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

View file

@ -1,31 +0,0 @@
version: "3.9"
volumes:
prod_database_data:
services:
# discord:
# build: .
database:
image: mysql/mysql-server
command: --default-authentication-plugin=mysql_native_password
restart: always
environment:
- MYSQL_DATABASE=carddrop
- MYSQL_USER=prod
- MYSQL_PASSWORD=prod
- MYSQL_ROOT_PASSWORD=root
- MYSQL_ROOT_HOST=0.0.0.0
ports:
- "3321:3306"
volumes:
- prod_database_data:/var/lib/mysql
phpmyadmin:
image: phpmyadmin
restart: always
ports:
- "3322:80"
environment:
- PMA_ARBITRARY=1

View file

@ -1,31 +0,0 @@
version: "3.9"
volumes:
stage_database_data:
services:
# discord:
# build: .
database:
image: mysql/mysql-server
command: --default-authentication-plugin=mysql_native_password
restart: always
environment:
- MYSQL_DATABASE=carddrop
- MYSQL_USER=stage
- MYSQL_PASSWORD=stage
- MYSQL_ROOT_PASSWORD=root
- MYSQL_ROOT_HOST=0.0.0.0
ports:
- "3311:3306"
volumes:
- stage_database_data:/var/lib/mysql
phpmyadmin:
image: phpmyadmin
restart: always
ports:
- "3312:80"
environment:
- PMA_ARBITRARY=1

View file

@ -1,31 +1,17 @@
version: "3.9"
volumes:
dev_database_data:
services:
# discord:
# build: .
database:
image: mysql/mysql-server
command: --default-authentication-plugin=mysql_native_password
restart: always
environment:
- MYSQL_DATABASE=carddrop
- MYSQL_USER=dev
- MYSQL_PASSWORD=dev
- MYSQL_ROOT_PASSWORD=root
- MYSQL_ROOT_HOST=0.0.0.0
- MYSQL_DATABASE=$DB_NAME
- MYSQL_USER=$DB_AUTH_USER
- MYSQL_PASSWORD=$DB_AUTH_PASS
- MYSQL_ROOT_PASSWORD=$DB_AUTH_PASS
- MYSQL_ROOT_HOST=$DB_ROOT_HOST
ports:
- "3301:3306"
- "$DB_PORT:3306"
volumes:
- dev_database_data:/var/lib/mysql
phpmyadmin:
image: phpmyadmin
restart: always
ports:
- "3302:80"
environment:
- PMA_ARBITRARY=1
- $DB_DATA_LOCATION:/var/lib/mysql

10331
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
{
"name": "card-drop",
"version": "0.3.0",
"version": "0.6.4",
"main": "./dist/bot.js",
"typings": "./dist",
"scripts": {
@ -8,6 +8,8 @@
"build": "tsc",
"start": "node ./dist/bot.js",
"test": "jest --passWithNoTests",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"db:up": "typeorm migration:run -d dist/database/dataSources/appDataSource.js",
"db:down": "typeorm migration:revert -d dist/database/dataSources/appDataSource.js",
"db:create": "typeorm migration:create ./src/database/migrations/app/new",
@ -24,27 +26,34 @@
"funding": "https://ko-fi.com/vylpes",
"dependencies": {
"@discordjs/rest": "^2.0.0",
"@types/clone-deep": "^4.0.4",
"@types/express": "^4.17.20",
"@types/jest": "^29.0.0",
"@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",
"glob": "^10.3.10",
"jest": "^29.0.0",
"jest-mock-extended": "^3.0.0",
"minimatch": "9.0.3",
"minimatch": "9.0.4",
"mysql": "^2.18.1",
"ts-jest": "^29.0.0",
"typeorm": "0.3.17"
"typeorm": "0.3.20",
"winston": "^3.11.0"
},
"resolutions": {
"**/undici": "^5.26.2"
"overrides": {
"undici": "^5.28.3"
},
"devDependencies": {
"@types/node": "^20.0.0",
"np": "^8.0.4",
"@typescript-eslint/eslint-plugin": "^6.16.0",
"@typescript-eslint/parser": "^6.16.0",
"eslint": "^8.56.0",
"np": "^9.0.0",
"typescript": "^5.0.0"
}
}

View file

@ -1,4 +1,5 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"baseBranches": ["develop"]
"baseBranches": ["develop"],
"labels": ["type/dependencies"]
}

View file

@ -3,21 +3,8 @@
export PATH="$HOME/.yarn/bin:$PATH"
export PATH="$HOME/.nodeuse/bin:$PATH"
export BOT_TOKEN=$(cat $HOME/scripts/card-drop/prod_key.txt)
cd ~/apps/card-drop/card-drop_prod \
&& git checkout main \
&& git fetch \
&& git pull \
&& docker compose --file docker-compose.prod.yml down \
&& (pm2 stop card-drop_prod || true) \
&& (pm2 delete card-drop_prod || true) \
&& cp .prod.env .env \
&& npm run clean \
&& npm ci \
&& npm run build \
&& docker compose --file docker-compose.prod.yml up -d \
&& echo "Sleeping for 10 seconds to let database load..." \
&& sleep 10 \
&& npm run db:up \
&& NODE_ENV=production pm2 start --name card-drop_prod dist/bot.js
cd ~/apps/card-drop/card-drop_prod
docker compose --file docker-compose.prod.yml up -d
sleep 10
cp .prod.env .env
pm2 restart card-drop_prod || pm2 start --name card-drop_prod dist/bot.js

View file

@ -3,21 +3,8 @@
export PATH="$HOME/.yarn/bin:$PATH"
export PATH="$HOME/.nodeuse/bin:$PATH"
export BOT_TOKEN=$(cat $HOME/scripts/card-drop/stage_key.txt)
cd ~/apps/card-drop/card-drop_stage \
&& git checkout develop \
&& git fetch \
&& git pull \
&& docker compose --file docker-compose.stage.yml down \
&& (pm2 stop card-drop_stage || true) \
&& (pm2 delete card-drop_stage || true) \
&& cp .stage.env .env \
&& npm run clean \
&& npm ci \
&& npm run build \
&& docker compose --file docker-compose.stage.yml up -d \
&& echo "Sleeping for 10 seconds to let database load..." \
&& sleep 10 \
&& npm run db:up \
&& NODE_ENV=production pm2 start --name card-drop_stage dist/bot.js
cd ~/apps/card-drop/card-drop_stage
docker compose --file docker-compose.stage.yml up -d
sleep 10
cp .stage.env .env
pm2 restart card-drop_stage || pm2 start --name card-drop_stage dist/bot.js

View file

@ -2,40 +2,92 @@ import { readFileSync } from "fs";
import path from "path";
import Config from "../database/entities/app/Config";
import { glob } from "glob";
import SeriesMetadata from "../contracts/SeriesMetadata";
import { SeriesMetadata } from "../contracts/SeriesMetadata";
import { CoreClient } from "../client/client";
import AppLogger from "../client/appLogger";
export interface CardMetadataResult {
IsSuccess: boolean;
ErrorMessage?: string;
}
export interface FindMetadataResult {
IsSuccess: boolean;
Result?: SeriesMetadata[];
Error?: {
File: string;
Message: string;
};
}
export default class CardMetadataFunction {
public static async Execute(overrideSafeMode: boolean = false): Promise<boolean> {
if (!overrideSafeMode && await Config.GetValue('safemode') == "true") return false;
public static async Execute(overrideSafeMode: boolean = false): Promise<CardMetadataResult> {
AppLogger.LogInfo("Functions/CardMetadataFunction", "Executing");
try {
CoreClient.Cards = await this.FindMetadataJSONs();
if (!overrideSafeMode && await Config.GetValue("safemode") == "true") {
AppLogger.LogWarn("Functions/CardMetadataFunction", "Safe Mode is active, refusing to resync");
console.log(`Loaded ${CoreClient.Cards.flatMap(x => x.cards).length} cards to database`);
} catch (e) {
console.error(e);
await Config.SetValue('safemode', 'true');
return false;
return {
IsSuccess: false,
ErrorMessage: "Safe mode is on and not overridden",
};
}
return true;
const cardResult = await this.FindMetadataJSONs();
if (cardResult.IsSuccess) {
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,
};
}
await Config.SetValue("safemode", "true");
AppLogger.LogError("Functions/CardMetadataFunction", `Safe Mode activated due to error: ${cardResult.Error!.Message}`);
return {
IsSuccess: false,
ErrorMessage: `${cardResult.Error!.File}: ${cardResult.Error!.Message}`,
};
}
private static async FindMetadataJSONs(): Promise<SeriesMetadata[]> {
private static async FindMetadataJSONs(): Promise<FindMetadataResult> {
const res: SeriesMetadata[] = [];
const seriesJSONs = await glob(path.join(process.cwd(), 'cards', '/**/*.json'));
const seriesJSONs = await glob(path.join(process.env.DATA_DIR!, "cards", "/**/*.json"));
for (let jsonPath of seriesJSONs) {
console.log(`Reading file ${jsonPath}`);
const jsonFile = readFileSync(jsonPath);
const parsedJson: SeriesMetadata[] = JSON.parse(jsonFile.toString());
for (const jsonPath of seriesJSONs) {
try {
AppLogger.LogVerbose("Functions/CardMetadataFunction", `Reading file ${jsonPath}`);
const jsonFile = readFileSync(jsonPath);
const parsedJson: SeriesMetadata[] = JSON.parse(jsonFile.toString());
res.push(...parsedJson);
res.push(...parsedJson);
} catch (e) {
AppLogger.LogError("Functions/CardMetadataFunction", `Error reading file ${jsonPath}: ${e}`);
return {
IsSuccess: false,
Error: {
File: jsonPath,
Message: `${e}`,
}
};
}
}
return res;
return {
IsSuccess: true,
Result: res,
};
}
}

View file

@ -14,6 +14,8 @@ const requiredConfigs: string[] = [
"BOT_OWNERID",
"BOT_CLIENTID",
"BOT_ENV",
"BOT_ADMINS",
"DATA_DIR",
"DB_HOST",
"DB_PORT",
"DB_AUTH_USER",
@ -21,8 +23,7 @@ const requiredConfigs: string[] = [
"DB_SYNC",
"DB_LOGGING",
"EXPRESS_PORT",
"GDRIVESYNC_WHITELIST",
]
];
requiredConfigs.forEach(config => {
if (!process.env[config]) {
@ -36,10 +37,9 @@ const client = new CoreClient([
]);
Registry.RegisterCommands();
Registry.RegisterEvents();
Registry.RegisterButtonEvents();
if (!existsSync(`${process.cwd()}/cards`) && process.env.GDRIVESYNC_AUTO && process.env.GDRIVESYNC_AUTO == 'true') {
if (!existsSync(`${process.env.DATA_DIR}/cards`) && process.env.GDRIVESYNC_AUTO && process.env.GDRIVESYNC_AUTO == "true") {
console.log("Card directory not found, syncing...");
CoreClient.AllowDrops = false;
@ -49,7 +49,7 @@ if (!existsSync(`${process.cwd()}/cards`) && process.env.GDRIVESYNC_AUTO && proc
console.error(error.code);
throw `Error while running sync command. Code: ${error.code}`;
} else {
console.log('Synced successfully.');
console.log("Synced successfully.");
CoreClient.AllowDrops = true;
}
});

View file

@ -3,28 +3,48 @@ import { ButtonEvent } from "../type/buttonEvent";
import Inventory from "../database/entities/app/Inventory";
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) {
if (!interaction.guild || !interaction.guildId) return;
if (!interaction.channel) return;
const cardNumber = interaction.customId.split(' ')[1];
const claimId = interaction.customId.split(' ')[2];
const droppedBy = interaction.customId.split(' ')[3];
await interaction.deferUpdate();
const cardNumber = interaction.customId.split(" ")[1];
const claimId = interaction.customId.split(" ")[2];
const droppedBy = interaction.customId.split(" ")[3];
const userId = interaction.user.id;
AppLogger.LogSilly("Button/Claim", `Parameters: cardNumber=${cardNumber}, claimId=${claimId}, droppedBy=${droppedBy}, userId=${userId}`);
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.channel.send(`${interaction.user}, Not enough currency! You need ${CardConstants.ClaimCost} currency, you have ${user.Currency}!`);
return;
}
const claimed = await eClaim.FetchOneByClaimId(claimId);
if (claimed) {
await interaction.reply('This card has already been claimed');
await interaction.channel.send(`${interaction.user}, This card has already been claimed!`);
return;
}
if (claimId == CoreClient.ClaimId && userId != droppedBy) {
await interaction.reply('The latest dropped card can only be claimed by the user who dropped it');
await interaction.channel.send(`${interaction.user}, The latest dropped card can only be claimed by the user who dropped it!`);
return;
}
await user.Save(User, user);
let inventory = await Inventory.FetchOneByCardNumberAndUserId(userId, cardNumber);
if (!inventory) {
@ -40,6 +60,20 @@ export default class Claim extends ButtonEvent {
await claim.Save(eClaim, claim);
await interaction.reply(`Card claimed by ${interaction.user}`);
const card = CardDropHelperMetadata.GetCardByCardNumber(cardNumber);
if (!card) {
return;
}
const imageFileName = card.card.path.split("/").pop()!;
const embed = CardDropHelperMetadata.GenerateDropEmbed(card, inventory.Quantity, imageFileName, interaction.user.username);
const row = CardDropHelperMetadata.GenerateDropButtons(card, claimId, interaction.user.id, true);
await interaction.editReply({
embeds: [ embed ],
components: [ row ],
});
}
}

View file

@ -0,0 +1,37 @@
import { ButtonInteraction } from "discord.js";
import { ButtonEvent } from "../type/buttonEvent";
import InventoryHelper from "../helpers/InventoryHelper";
import AppLogger from "../client/appLogger";
export default class Inventory extends ButtonEvent {
public override async execute(interaction: ButtonInteraction) {
if (!interaction.guild) return;
const userid = interaction.customId.split(" ")[1];
const page = interaction.customId.split(" ")[2];
AppLogger.LogSilly("Button/Inventory", `Parameters: userid=${userid}, page=${page}`);
const member = interaction.guild.members.cache.find(x => x.id == userid) || await interaction.guild.members.fetch(userid);
if (!member) {
await interaction.reply("Unable to find user.");
return;
}
try {
AppLogger.LogVerbose("Button/Inventory", `Generating inventory page ${page} for ${member.user.username} with id ${member.user.id}`);
const embed = await InventoryHelper.GenerateInventoryPage(member.user.username, member.user.id, Number(page));
await interaction.update({
embeds: [ embed.embed ],
components: [ embed.row ],
});
} catch (e) {
AppLogger.LogError("Button/Inventory", `Error generating inventory page for ${member.user.username} with id ${member.user.id}: ${e}`);
await interaction.reply("No page for user found.");
}
}
}

View file

@ -1,4 +1,4 @@
import { AttachmentBuilder, ButtonInteraction, DiscordAPIError } from "discord.js";
import { AttachmentBuilder, ButtonInteraction } from "discord.js";
import { ButtonEvent } from "../type/buttonEvent";
import { readFileSync } from "fs";
import { v4 } from "uuid";
@ -7,65 +7,75 @@ import Inventory from "../database/entities/app/Inventory";
import Config from "../database/entities/app/Config";
import CardDropHelperMetadata from "../helpers/CardDropHelperMetadata";
import path from "path";
import AppLogger from "../client/appLogger";
import User from "../database/entities/app/User";
import CardConstants from "../constants/CardConstants";
export default class Reroll extends ButtonEvent {
public override async execute(interaction: ButtonInteraction) {
if (!CoreClient.AllowDrops) {
await interaction.reply('Bot is currently syncing, please wait until its done.');
await interaction.reply("Bot is currently syncing, please wait until its done.");
return;
}
if (await Config.GetValue('safemode') == "true") {
await interaction.reply('Safe Mode has been activated, please resync to continue.');
if (await Config.GetValue("safemode") == "true") {
AppLogger.LogWarn("Button/Reroll", "Safe Mode is active, refusing to send next drop.");
await interaction.reply("Safe Mode has been activated, please resync to continue.");
return;
}
let user = await User.FetchOneById(User, interaction.user.id);
if (!user) {
user = new User(interaction.user.id, CardConstants.StartingCurrency);
await user.Save(User, user);
AppLogger.LogInfo("Commands/Drop", `New user (${interaction.user.id}) saved to the database`);
}
if (user.Currency < CardConstants.ClaimCost) {
await interaction.reply(`Not enough currency! You need ${CardConstants.ClaimCost} currency, you have ${user.Currency}!`);
return;
}
const randomCard = CardDropHelperMetadata.GetRandomCard();
if (!randomCard) {
await interaction.reply('Unable to fetch card, please try again.');
return;
}
let image: Buffer;
const imageFileName = randomCard.card.path.split("/").pop()!;
try {
image = readFileSync(path.join(process.cwd(), 'cards', randomCard.card.path));
} catch {
await interaction.reply(`Unable to fetch image for card ${randomCard.card.id}`);
await interaction.reply("Unable to fetch card, please try again.");
return;
}
await interaction.deferReply();
const attachment = new AttachmentBuilder(image, { name: imageFileName });
const inventory = await Inventory.FetchOneByCardNumberAndUserId(interaction.user.id, randomCard.card.id);
const quantityClaimed = inventory ? inventory.Quantity : 0;
const embed = CardDropHelperMetadata.GenerateDropEmbed(randomCard, quantityClaimed, imageFileName);
const claimId = v4();
const row = CardDropHelperMetadata.GenerateDropButtons(randomCard, claimId, interaction.user.id);
try {
AppLogger.LogVerbose("Button/Reroll", `Sending next drop: ${randomCard.card.id} (${randomCard.card.name})`);
const image = readFileSync(path.join(process.env.DATA_DIR!, "cards", randomCard.card.path));
const imageFileName = randomCard.card.path.split("/").pop()!;
const attachment = new AttachmentBuilder(image, { name: imageFileName });
const inventory = await Inventory.FetchOneByCardNumberAndUserId(interaction.user.id, randomCard.card.id);
const quantityClaimed = inventory ? inventory.Quantity : 0;
const embed = CardDropHelperMetadata.GenerateDropEmbed(randomCard, quantityClaimed, imageFileName);
const claimId = v4();
const row = CardDropHelperMetadata.GenerateDropButtons(randomCard, claimId, interaction.user.id);
await interaction.editReply({
embeds: [ embed ],
files: [ attachment ],
components: [ row ],
});
CoreClient.ClaimId = claimId;
} catch (e) {
console.error(e);
AppLogger.LogError("Button/Reroll", `Error sending next drop for card ${randomCard.card.id}: ${e}`);
if (e instanceof DiscordAPIError) {
await interaction.editReply(`Unable to send next drop. Please try again, and report this if it keeps happening. Code: ${e.code}`);
} else {
await interaction.editReply(`Unable to send next drop. Please try again, and report this if it keeps happening. Code: UNKNOWN`);
}
await interaction.editReply(`Unable to send next drop. Please try again, and report this if it keeps happening. (${randomCard.card.id})`);
}
CoreClient.ClaimId = claimId;
}
}

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

@ -0,0 +1,45 @@
import { ButtonInteraction } from "discord.js";
import { ButtonEvent } from "../type/buttonEvent";
import AppLogger from "../client/appLogger";
import SeriesHelper from "../helpers/SeriesHelper";
export default class Series extends ButtonEvent {
public override async execute(interaction: ButtonInteraction) {
const subaction = interaction.customId.split(" ")[1];
switch(subaction) {
case "view":
await this.ViewSeries(interaction);
break;
case "list":
await this.ListSeries(interaction);
break;
default:
AppLogger.LogWarn("Commands/Series", `Subaction doesn't exist: ${subaction}`);
interaction.reply("Subaction doesn't exist.");
}
}
private async ViewSeries(interaction: ButtonInteraction) {
const seriesid = interaction.customId.split(" ")[2];
const page = interaction.customId.split(" ")[3];
const embed = SeriesHelper.GenerateSeriesViewPage(Number(seriesid), Number(page));
await interaction.update({
embeds: [ embed!.embed ],
components: [ embed!.row ],
});
}
private async ListSeries(interaction: ButtonInteraction) {
const page = interaction.customId.split(" ")[2];
const embed = SeriesHelper.GenerateSeriesListPage(Number(page));
await interaction.update({
embeds: [ embed!.embed ],
components: [ embed!.row ],
});
}
}

211
src/buttonEvents/Trade.ts Normal file
View file

@ -0,0 +1,211 @@
import { ActionRowBuilder, ButtonBuilder, ButtonInteraction, ButtonStyle, EmbedBuilder } from "discord.js";
import { ButtonEvent } from "../type/buttonEvent";
import { CoreClient } from "../client/client";
import Inventory from "../database/entities/app/Inventory";
import EmbedColours from "../constants/EmbedColours";
import AppLogger from "../client/appLogger";
export default class Trade extends ButtonEvent {
public override async execute(interaction: ButtonInteraction) {
const action = interaction.customId.split(" ")[1];
AppLogger.LogSilly("Button/Trade", `Parameters: action=${action}`);
switch (action) {
case "accept":
await this.AcceptTrade(interaction);
break;
case "decline":
await this.DeclineTrade(interaction);
break;
}
}
private async AcceptTrade(interaction: ButtonInteraction) {
const user1UserId = interaction.customId.split(" ")[2];
const user2UserId = interaction.customId.split(" ")[3];
const user1CardNumber = interaction.customId.split(" ")[4];
const user2CardNumber = interaction.customId.split(" ")[5];
const expiry = interaction.customId.split(" ")[6];
const timeoutId = interaction.customId.split(" ")[7];
AppLogger.LogSilly("Button/Trade/AcceptTrade", `Parameters: user1UserId=${user1UserId}, user2UserId=${user2UserId}, user1CardNumber=${user1CardNumber}, user2CardNumber=${user2CardNumber}, expiry=${expiry}, timeoutId=${timeoutId}`);
const expiryDate = new Date(expiry);
if (expiryDate < new Date()) {
await interaction.reply("Trade has expired");
return;
}
if (interaction.user.id !== user2UserId) {
await interaction.reply("You are not the user who the trade is intended for");
return;
}
const user1Item = CoreClient.Cards
.flatMap(x => x.cards)
.find(x => x.id === user1CardNumber);
const user2Item = CoreClient.Cards
.flatMap(x => x.cards)
.find(x => x.id === user2CardNumber);
if (!user1Item || !user2Item) {
await interaction.reply("One or more of the items you are trying to trade does not exist.");
return;
}
const user1User = interaction.client.users.cache.get(user1UserId) || await interaction.client.users.fetch(user1UserId);
const user2User = interaction.client.users.cache.get(user2UserId) || await interaction.client.users.fetch(user2UserId);
const user1UserInventory1 = await Inventory.FetchOneByCardNumberAndUserId(user1UserId, user1CardNumber);
const user2UserInventory1 = await Inventory.FetchOneByCardNumberAndUserId(user2UserId, user2CardNumber);
if (!user1UserInventory1 || !user2UserInventory1) {
await interaction.reply("One or more of the items you are trying to trade does not exist.");
return;
}
if (user1UserInventory1.Quantity < 1 || user2UserInventory1.Quantity < 1) {
await interaction.reply("One or more of the items you are trying to trade does not exist.");
return;
}
user1UserInventory1.SetQuantity(user1UserInventory1.Quantity - 1);
user2UserInventory1.SetQuantity(user2UserInventory1.Quantity - 1);
await user1UserInventory1.Save(Inventory, user1UserInventory1);
await user2UserInventory1.Save(Inventory, user2UserInventory1);
let user1UserInventory2 = await Inventory.FetchOneByCardNumberAndUserId(user1UserId, user2CardNumber);
let user2UserInventory2 = await Inventory.FetchOneByCardNumberAndUserId(user2UserId, user1CardNumber);
if (!user1UserInventory2) {
user1UserInventory2 = new Inventory(user1UserId, user1CardNumber, 1);
} else {
user1UserInventory2.SetQuantity(user1UserInventory2.Quantity + 1);
}
if (!user2UserInventory2) {
user2UserInventory2 = new Inventory(user2UserId, user2CardNumber, 1);
} else {
user2UserInventory2.SetQuantity(user2UserInventory2.Quantity + 1);
}
await user1UserInventory2.Save(Inventory, user1UserInventory2);
await user2UserInventory2.Save(Inventory, user2UserInventory2);
clearTimeout(timeoutId);
const tradeEmbed = new EmbedBuilder()
.setTitle("Trade Accepted")
.setDescription(`Trade initiated between ${user1User.username} and ${user2User.username}`)
.setColor(EmbedColours.Success)
.setImage("https://i.imgur.com/9w5f1ls.gif")
.addFields([
{
name: `${user1User.username} Receives`,
value: `${user2Item.id}: ${user2Item.name}`,
inline: true,
},
{
name: `${user2User.username} Receives`,
value: `${user1Item.id}: ${user1Item.name}`,
inline: true,
},
{
name: "Complete",
value: new Date().toLocaleString(),
}
]);
const row = new ActionRowBuilder<ButtonBuilder>()
.addComponents([
new ButtonBuilder()
.setCustomId("trade expired accept")
.setLabel("Accept")
.setStyle(ButtonStyle.Success)
.setDisabled(true),
new ButtonBuilder()
.setCustomId("trade expired decline")
.setLabel("Decline")
.setStyle(ButtonStyle.Danger)
.setDisabled(true),
]);
await interaction.update({ embeds: [ tradeEmbed ], components: [ row ]});
}
private async DeclineTrade(interaction: ButtonInteraction) {
const user1UserId = interaction.customId.split(" ")[2];
const user2UserId = interaction.customId.split(" ")[3];
const user1CardNumber = interaction.customId.split(" ")[4];
const user2CardNumber = interaction.customId.split(" ")[5];
// No need to get expiry date
const timeoutId = interaction.customId.split(" ")[7];
AppLogger.LogSilly("Button/Trade/DeclineTrade", `Parameters: user1UserId=${user1UserId}, user2UserId=${user2UserId}, user1CardNumber=${user1CardNumber}, user2CardNumber=${user2CardNumber}, timeoutId=${timeoutId}`);
if (interaction.user.id != user1UserId && interaction.user.id !== user2UserId) {
await interaction.reply("You are not the user who the trade is intended for");
return;
}
const user1User = interaction.client.users.cache.get(user1UserId) || await interaction.client.users.fetch(user1UserId);
const user2User = interaction.client.users.cache.get(user2UserId) || await interaction.client.users.fetch(user2UserId);
const user1Item = CoreClient.Cards
.flatMap(x => x.cards)
.find(x => x.id === user1CardNumber);
const user2Item = CoreClient.Cards
.flatMap(x => x.cards)
.find(x => x.id === user2CardNumber);
if (!user1Item || !user2Item) {
await interaction.reply("One or more of the items you are trying to trade does not exist.");
return;
}
clearTimeout(timeoutId);
const tradeEmbed = new EmbedBuilder()
.setTitle("Trade Declined")
.setDescription(`Trade initiated between ${user1User.username} and ${user2User.username}`)
.setColor(EmbedColours.Error)
.setImage("https://i.imgur.com/9w5f1ls.gif")
.addFields([
{
name: `${user1User.username} Receives`,
value: `${user2Item.id}: ${user2Item.name}`,
inline: true,
},
{
name: `${user2User.username} Receives`,
value: `${user1Item.id}: ${user1Item.name}`,
inline: true,
},
{
name: "Declined",
value: new Date().toLocaleString(),
}
]);
const row = new ActionRowBuilder<ButtonBuilder>()
.addComponents([
new ButtonBuilder()
.setCustomId("trade expired accept")
.setLabel("Accept")
.setStyle(ButtonStyle.Success)
.setDisabled(true),
new ButtonBuilder()
.setCustomId("trade expired decline")
.setLabel("Decline")
.setStyle(ButtonStyle.Danger)
.setDisabled(true),
]);
await interaction.update({ embeds: [ tradeEmbed ], components: [ row ]});
}
}

65
src/client/appLogger.ts Normal file
View file

@ -0,0 +1,65 @@
import { Logger, createLogger, format, transports } from "winston";
export default class AppLogger {
public static Logger: Logger;
public static InitialiseLogger(logLevel: string, outputToConsole: boolean) {
const customFormat = format.printf(({ level, message, timestamp, label }) => {
return `${timestamp} [${label}] ${level}: ${message}`;
});
const logger = createLogger({
level: logLevel,
format: format.combine(
format.timestamp({
format: "YYYY-MM-DD HH:mm:ss"
}),
format.errors({ stack: true }),
format.splat(),
customFormat,
),
defaultMeta: { service: "bot" },
transports: [
new transports.File({ filename: "error.log", level: "error" }),
new transports.File({ filename: "combined.log" }),
],
});
if (outputToConsole) {
logger.add(new transports.Console({
format: format.combine(
format.colorize(),
format.timestamp(),
customFormat,
)}));
}
AppLogger.Logger = logger;
AppLogger.LogInfo("AppLogger", `Log Level: ${logLevel}`);
}
public static LogError(label: string, message: string) {
AppLogger.Logger.error({ label, message });
}
public static LogWarn(label: string, message: string) {
AppLogger.Logger.warn({ label, message });
}
public static LogInfo(label: string, message: string) {
AppLogger.Logger.info({ label, message });
}
public static LogVerbose(label: string, message: string) {
AppLogger.Logger.verbose({ label, message });
}
public static LogDebug(label: string, message: string) {
AppLogger.Logger.debug({ label, message });
}
public static LogSilly(label: string, message: string) {
AppLogger.Logger.silly({ label, message });
}
}

View file

@ -1,28 +1,31 @@
import { Client } from "discord.js";
import { Client, DMChannel, Guild, GuildBan, GuildMember, Message, NonThreadGuildBasedChannel, PartialGuildMember, PartialMessage } from "discord.js";
import * as dotenv from "dotenv";
import { EventType } from "../constants/EventType";
import ICommandItem from "../contracts/ICommandItem";
import IEventItem from "../contracts/IEventItem";
import EventExecutors from "../contracts/EventExecutors";
import { Command } from "../type/command";
import { Events } from "./events";
import { Util } from "./util";
import IButtonEventItem from "../contracts/IButtonEventItem";
import IButtonEventItem from "../contracts/ButtonEventItem";
import { ButtonEvent } from "../type/buttonEvent";
import AppDataSource from "../database/dataSources/appDataSource";
import { Environment } from "../constants/Environment";
import Webhooks from "../webhooks";
import CardMetadataFunction from "../Functions/CardMetadataFunction";
import SeriesMetadata from "../contracts/SeriesMetadata";
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[];
private static _eventItems: IEventItem[];
private static _eventExecutors: EventExecutors;
private static _buttonEvents: IButtonEventItem[];
private _events: Events;
private _util: Util;
private _webhooks: Webhooks;
private _timerHelper: TimerHelper;
public static ClaimId: string;
public static Environment: Environment;
@ -33,8 +36,8 @@ export class CoreClient extends Client {
return this._commandItems;
}
public static get eventItems(): IEventItem[] {
return this._eventItems;
public static get eventExecutors(): EventExecutors {
return this._eventExecutors;
}
public static get buttonEvents(): IButtonEventItem[] {
@ -45,44 +48,56 @@ export class CoreClient extends Client {
super({ intents: intents });
dotenv.config();
CoreClient.Environment = Number(process.env.BOT_ENV);
const loglevel = process.env.BOT_LOGLEVEL ?? "info";
AppLogger.InitialiseLogger(loglevel, CoreClient.Environment == Environment.Local);
AppLogger.LogInfo("Client", "Initialising Client");
CoreClient._commandItems = [];
CoreClient._eventItems = [];
CoreClient._buttonEvents = [];
this._events = new Events();
this._util = new Util();
this._webhooks = new Webhooks();
this._timerHelper = new TimerHelper();
CoreClient.Environment = Number(process.env.BOT_ENV);
console.log(`Bot Environment: ${CoreClient.Environment}`);
AppLogger.LogInfo("Client", `Environment: ${CoreClient.Environment}`);
CoreClient.AllowDrops = true;
}
public async start() {
if (!process.env.BOT_TOKEN) {
console.error("BOT_TOKEN is not defined in .env");
AppLogger.LogError("Client", "BOT_TOKEN is not defined in .env");
return;
}
await AppDataSource.initialize()
.then(() => console.log("App Data Source Initialised"))
.catch(err => console.error("Error initialising App Data Source", err));
.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);
throw err;
});
super.on("interactionCreate", this._events.onInteractionCreate);
super.on("ready", this._events.onReady);
await CardMetadataFunction.Execute(true);
this._util.loadEvents(this, CoreClient._eventItems);
this._util.loadEvents(this, CoreClient._eventExecutors);
this._util.loadSlashCommands(this);
this._webhooks.start();
console.log(`Registered Commands: ${CoreClient._commandItems.flatMap(x => x.Name).join(", ")}`);
console.log(`Registered Events: ${CoreClient._eventItems.flatMap(x => x.EventType).join(", ")}`);
console.log(`Registered Buttons: ${CoreClient._buttonEvents.flatMap(x => x.ButtonId).join(", ")}`);
await super.login(process.env.BOT_TOKEN);
}
@ -94,21 +109,287 @@ export class CoreClient extends Client {
ServerId: serverId,
};
if (environment &= CoreClient.Environment) {
if ((environment & CoreClient.Environment) == CoreClient.Environment) {
CoreClient._commandItems.push(item);
AppLogger.LogVerbose("Client", `Registered Command: ${name}`);
}
}
public static RegisterEvent(eventType: EventType, func: Function, environment: Environment = Environment.All) {
const item: IEventItem = {
EventType: eventType,
ExecutionFunction: func,
Environment: environment,
};
if (environment &= CoreClient.Environment) {
CoreClient._eventItems.push(item);
public static RegisterChannelCreateEvent(fn: (channel: NonThreadGuildBasedChannel) => void) {
if (this._eventExecutors) {
this._eventExecutors.ChannelCreate.push(fn);
} else {
this._eventExecutors = {
ChannelCreate: [ fn ],
ChannelDelete: [],
ChannelUpdate: [],
GuildBanAdd: [],
GuildBanRemove: [],
GuildCreate: [],
GuildMemberAdd: [],
GuildMemberRemove: [],
GuildMemebrUpdate: [],
MessageCreate: [],
MessageDelete: [],
MessageUpdate: [],
};
}
AppLogger.LogVerbose("Client", "Registered Channel Create Event");
}
public static RegisterChannelDeleteEvent(fn: (channel: DMChannel | NonThreadGuildBasedChannel) => void) {
if (this._eventExecutors) {
this._eventExecutors.ChannelDelete.push(fn);
} else {
this._eventExecutors = {
ChannelCreate: [],
ChannelDelete: [ fn ],
ChannelUpdate: [],
GuildBanAdd: [],
GuildBanRemove: [],
GuildCreate: [],
GuildMemberAdd: [],
GuildMemberRemove: [],
GuildMemebrUpdate: [],
MessageCreate: [],
MessageDelete: [],
MessageUpdate: [],
};
}
AppLogger.LogVerbose("Client", "Registered Channel Delete Event");
}
public static RegisterChannelUpdateEvent(fn: (channel: DMChannel | NonThreadGuildBasedChannel) => void) {
if (this._eventExecutors) {
this._eventExecutors.ChannelCreate.push(fn);
} else {
this._eventExecutors = {
ChannelCreate: [],
ChannelDelete: [],
ChannelUpdate: [ fn ],
GuildBanAdd: [],
GuildBanRemove: [],
GuildCreate: [],
GuildMemberAdd: [],
GuildMemberRemove: [],
GuildMemebrUpdate: [],
MessageCreate: [],
MessageDelete: [],
MessageUpdate: [],
};
}
AppLogger.LogVerbose("Client", "Registered Channel Update Event");
}
public static RegisterGuildBanAddEvent(fn: (ban: GuildBan) => void) {
if (this._eventExecutors) {
this._eventExecutors.GuildBanAdd.push(fn);
} else {
this._eventExecutors = {
ChannelCreate: [],
ChannelDelete: [],
ChannelUpdate: [],
GuildBanAdd: [ fn ],
GuildBanRemove: [],
GuildCreate: [],
GuildMemberAdd: [],
GuildMemberRemove: [],
GuildMemebrUpdate: [],
MessageCreate: [],
MessageDelete: [],
MessageUpdate: [],
};
}
AppLogger.LogVerbose("Client", "Registered Guild Ban Add Event");
}
public static RegisterGuildBanRemoveEvent(fn: (channel: GuildBan) => void) {
if (this._eventExecutors) {
this._eventExecutors.GuildBanRemove.push(fn);
} else {
this._eventExecutors = {
ChannelCreate: [],
ChannelDelete: [],
ChannelUpdate: [],
GuildBanAdd: [],
GuildBanRemove: [ fn ],
GuildCreate: [],
GuildMemberAdd: [],
GuildMemberRemove: [],
GuildMemebrUpdate: [],
MessageCreate: [],
MessageDelete: [],
MessageUpdate: [],
};
}
AppLogger.LogVerbose("Client", "Registered Guild Ban Remove Event");
}
public static RegisterGuildCreateEvent(fn: (guild: Guild) => void) {
if (this._eventExecutors) {
this._eventExecutors.GuildCreate.push(fn);
} else {
this._eventExecutors = {
ChannelCreate: [],
ChannelDelete: [],
ChannelUpdate: [],
GuildBanAdd: [],
GuildBanRemove: [],
GuildCreate: [ fn ],
GuildMemberAdd: [],
GuildMemberRemove: [],
GuildMemebrUpdate: [],
MessageCreate: [],
MessageDelete: [],
MessageUpdate: [],
};
}
AppLogger.LogVerbose("Client", "Registered Guild Create Event");
}
public static RegisterGuildMemberAddEvent(fn: (member: GuildMember) => void) {
if (this._eventExecutors) {
this._eventExecutors.GuildMemberAdd.push(fn);
} else {
this._eventExecutors = {
ChannelCreate: [],
ChannelDelete: [],
ChannelUpdate: [],
GuildBanAdd: [],
GuildBanRemove: [],
GuildCreate: [],
GuildMemberAdd: [ fn ],
GuildMemberRemove: [],
GuildMemebrUpdate: [],
MessageCreate: [],
MessageDelete: [],
MessageUpdate: [],
};
}
AppLogger.LogVerbose("Client", "Registered Guild Member Add Event");
}
public static RegisterGuildMemberRemoveEvent(fn: (member: GuildMember | PartialGuildMember) => void) {
if (this._eventExecutors) {
this._eventExecutors.GuildMemberRemove.push(fn);
} else {
this._eventExecutors = {
ChannelCreate: [],
ChannelDelete: [],
ChannelUpdate: [],
GuildBanAdd: [],
GuildBanRemove: [],
GuildCreate: [],
GuildMemberAdd: [],
GuildMemberRemove: [ fn ],
GuildMemebrUpdate: [],
MessageCreate: [],
MessageDelete: [],
MessageUpdate: [],
};
}
AppLogger.LogVerbose("Client", "Registered Guild Member Remove Event");
}
public static GuildMemebrUpdate(fn: (oldMember: GuildMember | PartialGuildMember, newMember: GuildMember) => void) {
if (this._eventExecutors) {
this._eventExecutors.GuildMemebrUpdate.push(fn);
} else {
this._eventExecutors = {
ChannelCreate: [],
ChannelDelete: [],
ChannelUpdate: [],
GuildBanAdd: [],
GuildBanRemove: [],
GuildCreate: [],
GuildMemberAdd: [],
GuildMemberRemove: [],
GuildMemebrUpdate: [ fn ],
MessageCreate: [],
MessageDelete: [],
MessageUpdate: [],
};
}
AppLogger.LogVerbose("Client", "Registered Guild Member Update Event");
}
public static RegisterMessageCreateEvent(fn: (message: Message<boolean>) => void) {
if (this._eventExecutors) {
this._eventExecutors.MessageCreate.push(fn);
} else {
this._eventExecutors = {
ChannelCreate: [],
ChannelDelete: [],
ChannelUpdate: [],
GuildBanAdd: [],
GuildBanRemove: [],
GuildCreate: [],
GuildMemberAdd: [],
GuildMemberRemove: [],
GuildMemebrUpdate: [],
MessageCreate: [ fn ],
MessageDelete: [],
MessageUpdate: [],
};
}
AppLogger.LogVerbose("Client", "Registered Message Create Event");
}
public static RegisterMessageDeleteEvent(fn: (message: Message<boolean> | PartialMessage) => void) {
if (this._eventExecutors) {
this._eventExecutors.MessageDelete.push(fn);
} else {
this._eventExecutors = {
ChannelCreate: [],
ChannelDelete: [],
ChannelUpdate: [],
GuildBanAdd: [],
GuildBanRemove: [],
GuildCreate: [],
GuildMemberAdd: [],
GuildMemberRemove: [],
GuildMemebrUpdate: [],
MessageCreate: [],
MessageDelete: [ fn ],
MessageUpdate: [],
};
}
AppLogger.LogVerbose("Client", "Registered Message Delete Event");
}
public static RegisterMessageUpdateEvent(fn: (oldMessage: Message<boolean> | PartialMessage, newMessage: Message<boolean> | PartialMessage) => void) {
if (this._eventExecutors) {
this._eventExecutors.MessageUpdate.push(fn);
} else {
this._eventExecutors = {
ChannelCreate: [],
ChannelDelete: [],
ChannelUpdate: [],
GuildBanAdd: [],
GuildBanRemove: [],
GuildCreate: [],
GuildMemberAdd: [],
GuildMemberRemove: [],
GuildMemebrUpdate: [],
MessageCreate: [],
MessageDelete: [],
MessageUpdate: [ fn ],
};
}
AppLogger.LogVerbose("Client", "Registered Message Update Event");
}
public static RegisterButtonEvent(buttonId: string, event: ButtonEvent, environment: Environment = Environment.All) {
@ -118,8 +399,10 @@ export class CoreClient extends Client {
Environment: environment,
};
if (environment &= CoreClient.Environment) {
if ((environment & CoreClient.Environment) == CoreClient.Environment) {
CoreClient._buttonEvents.push(item);
AppLogger.LogVerbose("Client", `Registered Button Event: ${buttonId}`);
}
}
}

View file

@ -1,22 +1,28 @@
import { Interaction } from "discord.js";
import ChatInputCommand from "./interactionCreate/ChatInputCommand";
import Button from "./interactionCreate/Button";
import AppLogger from "./appLogger";
import NewUserDiscovery from "./interactionCreate/middleware/NewUserDiscovery";
export class Events {
public async onInteractionCreate(interaction: Interaction) {
if (!interaction.guildId) return;
await NewUserDiscovery(interaction);
if (interaction.isChatInputCommand()) {
AppLogger.LogVerbose("Client", `ChatInputCommand: ${interaction.commandName}`);
ChatInputCommand.onChatInput(interaction);
}
if (interaction.isButton()) {
AppLogger.LogVerbose("Client", `Button: ${interaction.customId}`);
Button.onButtonClicked(interaction);
}
}
// Emit when bot is logged in and ready to use
public onReady() {
console.log("Ready");
AppLogger.LogInfo("Client", "Ready");
}
}

View file

@ -1,17 +1,29 @@
import { ButtonInteraction, Interaction } from "discord.js";
import { ButtonInteraction } from "discord.js";
import { CoreClient } from "../client";
import AppLogger from "../appLogger";
export default class Button {
public static async onButtonClicked(interaction: ButtonInteraction) {
if (!interaction.isButton) return;
const item = CoreClient.buttonEvents.find(x => x.ButtonId == interaction.customId.split(' ')[0]);
const item = CoreClient.buttonEvents.find(x => x.ButtonId == interaction.customId.split(" ")[0]);
if (!item) {
await interaction.reply('Event not found');
AppLogger.LogVerbose("Button", `Event not found: ${interaction.customId}`);
await interaction.reply("Event not found");
return;
}
item.Event.execute(interaction);
try {
AppLogger.LogDebug("Button", `Executing ${interaction.customId}`);
item.Event.execute(interaction);
} catch (e) {
AppLogger.LogError("Button", `Error occurred while executing event: ${interaction.customId}`);
AppLogger.LogError("Button", e as string);
await interaction.reply("An error occurred while executing the event");
}
}
}

View file

@ -1,6 +1,7 @@
import { Interaction } from "discord.js";
import { CoreClient } from "../client";
import ICommandItem from "../../contracts/ICommandItem";
import AppLogger from "../appLogger";
export default class ChatInputCommand {
public static async onChatInput(interaction: Interaction) {
@ -13,7 +14,9 @@ export default class ChatInputCommand {
if (!itemForServer) {
if (!item) {
await interaction.reply('Command not found');
AppLogger.LogVerbose("ChatInputCommand", `Command not found: ${interaction.commandName}`);
await interaction.reply("Command not found");
return;
}
@ -22,6 +25,15 @@ export default class ChatInputCommand {
itemToUse = itemForServer;
}
itemToUse.Command.execute(interaction);
try {
AppLogger.LogDebug("Command", `Executing ${interaction.commandName}`);
itemToUse.Command.execute(interaction);
} catch (e) {
AppLogger.LogError("ChatInputCommand", `Error occurred while executing command: ${interaction.commandName}`);
AppLogger.LogError("ChatInputCommand", e as string);
await interaction.reply("An error occurred while executing the command");
}
}
}

View file

@ -0,0 +1,15 @@
import { Interaction } from "discord.js";
import User from "../../../database/entities/app/User";
import CardConstants from "../../../constants/CardConstants";
import AppLogger from "../../appLogger";
export default async function NewUserDiscovery(interaction: Interaction) {
const existingUser = await User.FetchOneById(User, interaction.user.id);
if (existingUser) return;
const newUser = new User(interaction.user.id, CardConstants.StartingCurrency);
await newUser.Save(User, newUser);
AppLogger.LogInfo("NewUserDiscovery", `Discovered new user ${interaction.user.id}`);
}

View file

@ -1,7 +1,7 @@
import { Client, REST, Routes, SlashCommandBuilder } from "discord.js";
import { EventType } from "../constants/EventType";
import IEventItem from "../contracts/IEventItem";
import EventExecutors from "../contracts/EventExecutors";
import { CoreClient } from "./client";
import AppLogger from "./appLogger";
export class Util {
public loadSlashCommands(client: Client) {
@ -10,25 +10,27 @@ export class Util {
const globalCommands = registeredCommands.filter(x => !x.ServerId);
const guildCommands = registeredCommands.filter(x => x.ServerId);
const globalCommandData: SlashCommandBuilder[] = [];
const globalCommandData: Omit<SlashCommandBuilder, "addSubcommand" | "addSubcommandGroup">[] = [];
for (let command of globalCommands) {
for (const command of globalCommands) {
if (!command.Command.CommandBuilder) continue;
if (command.Environment &= CoreClient.Environment) {
if ((command.Environment & CoreClient.Environment) == CoreClient.Environment) {
globalCommandData.push(command.Command.CommandBuilder);
}
}
const guildIds: string[] = [];
for (let command of guildCommands) {
for (const command of guildCommands) {
if (!guildIds.find(x => x == command.ServerId)) {
guildIds.push(command.ServerId!);
}
}
const rest = new REST({ version: '10' }).setToken(process.env.BOT_TOKEN!);
const rest = new REST({ version: "10" }).setToken(process.env.BOT_TOKEN!);
AppLogger.LogVerbose("Util", `REST PUT: ${globalCommandData.flatMap(x => x.name).join(", ")}`);
rest.put(
Routes.applicationCommands(process.env.BOT_CLIENTID!),
@ -37,71 +39,43 @@ export class Util {
}
);
for (let guild of guildIds) {
const guildCommandData: SlashCommandBuilder[] = [];
for (const guild of guildIds) {
const guildCommandData: Omit<SlashCommandBuilder, "addSubcommand" | "addSubcommandGroup">[] = [];
for (let command of guildCommands.filter(x => x.ServerId == guild)) {
for (const command of guildCommands.filter(x => x.ServerId == guild)) {
if (!command.Command.CommandBuilder) continue;
if (command.Environment &= CoreClient.Environment) {
if ((command.Environment & CoreClient.Environment) == CoreClient.Environment) {
guildCommandData.push(command.Command.CommandBuilder);
}
}
if (!client.guilds.cache.has(guild)) continue;
AppLogger.LogVerbose("Util", `REST PUT: ${guild} - ${guildCommandData.flatMap(x => x.name).join(", ")}`);
rest.put(
Routes.applicationGuildCommands(process.env.BOT_CLIENTID!, guild),
{
body: guildCommandData
}
)
);
}
}
// Load the events
loadEvents(client: Client, events: IEventItem[]) {
events.forEach((e) => {
switch(e.EventType) {
case EventType.ChannelCreate:
client.on('channelCreate', (channel) => e.ExecutionFunction(channel));
break;
case EventType.ChannelDelete:
client.on('channelDelete', (channel) => e.ExecutionFunction(channel));
break;
case EventType.ChannelUpdate:
client.on('channelUpdate', (channel) => e.ExecutionFunction(channel));
break;
case EventType.GuildBanAdd:
client.on('guildBanAdd', (ban) => e.ExecutionFunction(ban));
break;
case EventType.GuildBanRemove:
client.on('guildBanRemove', (ban) => e.ExecutionFunction(ban));
break;
case EventType.GuildCreate:
client.on('guildCreate', (guild) => e.ExecutionFunction(guild));
break;
case EventType.GuildMemberAdd:
client.on('guildMemberAdd', (member) => e.ExecutionFunction(member));
break;
case EventType.GuildMemberRemove:
client.on('guildMemberRemove', (member) => e.ExecutionFunction(member));
break;
case EventType.GuildMemberUpdate:
client.on('guildMemberUpdate', (oldMember, newMember) => e.ExecutionFunction(oldMember, newMember));
break;
case EventType.MessageCreate:
client.on('messageCreate', (message) => e.ExecutionFunction(message));
break;
case EventType.MessageDelete:
client.on('messageDelete', (message) => e.ExecutionFunction(message));
break;
case EventType.MessageUpdate:
client.on('messageUpdate', (oldMessage, newMessage) => e.ExecutionFunction(oldMessage, newMessage));
break;
default:
console.error('Event not implemented.');
}
});
loadEvents(client: Client, events: EventExecutors) {
client.on("channelCreate", (channel) => events.ChannelCreate.forEach((fn) => fn(channel)));
client.on("channelDelete", (channel) => events.ChannelDelete.forEach((fn) => fn(channel)));
client.on("channelUpdate", (channel) => events.ChannelUpdate.forEach((fn) => fn(channel)));
client.on("guildBanAdd", (ban) => events.GuildBanAdd.forEach((fn) => fn(ban)));
client.on("guildBanRemove", (ban) => events.GuildBanRemove.forEach((fn) => fn(ban)));
client.on("guildCreate", (guild) => events.GuildCreate.forEach((fn) => fn(guild)));
client.on("guildMemberAdd", (member) => events.GuildMemberAdd.forEach((fn) => fn(member)));
client.on("guildMemberRemove", (member) => events.GuildMemberRemove.forEach((fn) => fn(member)));
client.on("guildMemberUpdate", (oldMember, newMember) => events.GuildMemebrUpdate.forEach((fn) => fn(oldMember, newMember)));
client.on("messageCreate", (message) => events.MessageCreate.forEach((fn) => fn(message)));
client.on("messageDelete", (message) => events.MessageDelete.forEach((fn) => fn(message)));
client.on("messageUpdate", (oldMessage, newMessage) => events.MessageUpdate.forEach((fn) => fn(oldMessage, newMessage)));
}
}

View file

@ -6,9 +6,9 @@ export default class About extends Command {
constructor() {
super();
super.CommandBuilder = new SlashCommandBuilder()
.setName('about')
.setDescription('About Bot');
this.CommandBuilder = new SlashCommandBuilder()
.setName("about")
.setDescription("About Bot");
}
public override async execute(interaction: CommandInteraction) {

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);
const 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

@ -1,4 +1,4 @@
import { AttachmentBuilder, CommandInteraction, DiscordAPIError, SlashCommandBuilder } from "discord.js";
import { AttachmentBuilder, CommandInteraction, SlashCommandBuilder } from "discord.js";
import { Command } from "../type/command";
import { readFileSync } from "fs";
import { CoreClient } from "../client/client";
@ -7,73 +7,85 @@ import Inventory from "../database/entities/app/Inventory";
import Config from "../database/entities/app/Config";
import CardDropHelperMetadata from "../helpers/CardDropHelperMetadata";
import path from "path";
import AppLogger from "../client/appLogger";
import User from "../database/entities/app/User";
import CardConstants from "../constants/CardConstants";
export default class Drop extends Command {
constructor() {
super();
super.CommandBuilder = new SlashCommandBuilder()
.setName('drop')
.setDescription('Summon a new card drop');
this.CommandBuilder = new SlashCommandBuilder()
.setName("drop")
.setDescription("Summon a new card drop");
}
public override async execute(interaction: CommandInteraction) {
if (!CoreClient.AllowDrops) {
await interaction.reply('Bot is currently syncing, please wait until its done.');
await interaction.reply("Bot is currently syncing, please wait until its done.");
return;
}
if (await Config.GetValue('safemode') == "true") {
await interaction.reply('Safe Mode has been activated, please resync to continue.');
if (await Config.GetValue("safemode") == "true") {
AppLogger.LogWarn("Commands/Drop", "Safe Mode is active, refusing to send next drop.");
await interaction.reply("Safe Mode has been activated, please resync to continue.");
return;
}
let user = await User.FetchOneById(User, interaction.user.id);
if (!user) {
user = new User(interaction.user.id, CardConstants.StartingCurrency);
await user.Save(User, user);
AppLogger.LogInfo("Commands/Drop", `New user (${interaction.user.id}) saved to the database`);
}
if (user.Currency < CardConstants.ClaimCost) {
await interaction.reply(`Not enough currency! You need ${CardConstants.ClaimCost} currency, you have ${user.Currency}!`);
return;
}
const randomCard = CardDropHelperMetadata.GetRandomCard();
if (!randomCard) {
await interaction.reply('Unable to fetch card, please try again.');
return;
}
AppLogger.LogWarn("Commands/Drop", "Unable to fetch card, please try again. (randomCard is null)");
let image: Buffer;
const imageFileName = randomCard.card.path.split("/").pop()!;
try {
image = readFileSync(path.join(process.cwd(), 'cards', randomCard.card.path));
} catch {
await interaction.reply(`Unable to fetch image for card ${randomCard.card.id}`);
await interaction.reply("Unable to fetch card, please try again.");
return;
}
await interaction.deferReply();
const attachment = new AttachmentBuilder(image, { name: imageFileName });
const inventory = await Inventory.FetchOneByCardNumberAndUserId(interaction.user.id, randomCard.card.id);
const quantityClaimed = inventory ? inventory.Quantity : 0;
const embed = CardDropHelperMetadata.GenerateDropEmbed(randomCard, quantityClaimed, imageFileName);
const claimId = v4();
const row = CardDropHelperMetadata.GenerateDropButtons(randomCard, claimId, interaction.user.id);
try {
const image = readFileSync(path.join(process.env.DATA_DIR!, "cards", randomCard.card.path));
const imageFileName = randomCard.card.path.split("/").pop()!;
const attachment = new AttachmentBuilder(image, { name: imageFileName });
const inventory = await Inventory.FetchOneByCardNumberAndUserId(interaction.user.id, randomCard.card.id);
const quantityClaimed = inventory ? inventory.Quantity : 0;
const embed = CardDropHelperMetadata.GenerateDropEmbed(randomCard, quantityClaimed, imageFileName);
const claimId = v4();
const row = CardDropHelperMetadata.GenerateDropButtons(randomCard, claimId, interaction.user.id);
await interaction.editReply({
embeds: [ embed ],
files: [ attachment ],
components: [ row ],
});
} catch (e) {
console.error(e);
if (e instanceof DiscordAPIError) {
await interaction.editReply(`Unable to send next drop. Please try again, and report this if it keeps happening. Code: ${e.code}`);
} else {
await interaction.editReply(`Unable to send next drop. Please try again, and report this if it keeps happening. Code: UNKNOWN`);
}
CoreClient.ClaimId = claimId;
} catch (e) {
AppLogger.LogError("Commands/Drop", `Error sending next drop for card ${randomCard.card.id}: ${e}`);
await interaction.editReply(`Unable to send next drop. Please try again, and report this if it keeps happening. (${randomCard.card.id})`);
}
CoreClient.ClaimId = claimId;
}
}

View file

@ -4,42 +4,59 @@ import { ExecException, exec } from "child_process";
import { CoreClient } from "../client/client";
import Config from "../database/entities/app/Config";
import CardMetadataFunction from "../Functions/CardMetadataFunction";
import AppLogger from "../client/appLogger";
export default class Gdrivesync extends Command {
constructor() {
super();
super.CommandBuilder = new SlashCommandBuilder()
.setName('gdrivesync')
.setDescription('Sync google drive to the bot')
this.CommandBuilder = new SlashCommandBuilder()
.setName("gdrivesync")
.setDescription("Sync google drive to the bot")
.setDefaultMemberPermissions(PermissionsBitField.Flags.Administrator);
}
public override async execute(interaction: CommandInteraction<CacheType>) {
if (!interaction.isChatInputCommand()) return;
const whitelistedUsers = process.env.GDRIVESYNC_WHITELIST!.split(',');
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;
}
await interaction.reply('Syncing, this might take a while...');
await interaction.reply({
content: "Syncing, this might take a while...",
ephemeral: true,
});
CoreClient.AllowDrops = false;
exec(`rclone sync card-drop-gdrive: ${process.cwd()}/cards`, async (error: ExecException | null) => {
AppLogger.LogInfo("Commands/GDriveSync", "Syncing google drive to the bot");
exec(`rclone sync card-drop-gdrive: ${process.env.DATA_DIR}/cards`, async (error: ExecException | null) => {
if (error) {
AppLogger.LogError("Commands/GDriveSync", `Error while running sync command: ${error.code}, ${error.message}`);
AppLogger.LogWarn("Commands/GDriveSync", "Safe mode activated");
await interaction.editReply(`Error while running sync command. Safe Mode has been activated. Code: ${error.code}`);
await Config.SetValue('safemode', 'true');
await Config.SetValue("safemode", "true");
} else {
await CardMetadataFunction.Execute();
const result = await CardMetadataFunction.Execute(true);
await interaction.editReply('Synced successfully.');
if (result.IsSuccess) {
AppLogger.LogInfo("Commands/GDriveSync", "Synced successfully");
CoreClient.AllowDrops = true;
await Config.SetValue('safemode', 'false');
await interaction.editReply("Synced successfully.");
CoreClient.AllowDrops = true;
await Config.SetValue("safemode", "false");
} else {
AppLogger.LogError("Commands/GDriveSync", `Error while running sync command: ${result.ErrorMessage}`);
await interaction.editReply(`Sync failed \`\`\`${result.ErrorMessage}\`\`\``);
}
}
});
}

118
src/commands/give.ts Normal file
View file

@ -0,0 +1,118 @@
import { CacheType, CommandInteraction, PermissionsBitField, SlashCommandBuilder } from "discord.js";
import { Command } from "../type/command";
import { CoreClient } from "../client/client";
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() {
super();
this.CommandBuilder = new SlashCommandBuilder()
.setName("give")
.setDescription("Give a user a card manually, in case bot breaks")
.setDefaultMemberPermissions(PermissionsBitField.Flags.Administrator)
.addSubcommand(x =>
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("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;
}
if (await Config.GetValue("safemode") == "true") {
await interaction.reply("Safe Mode has been activated, please resync to continue.");
return;
}
const cardNumber = interaction.options.get("cardnumber", true);
const user = interaction.options.get("user", true).user!;
AppLogger.LogSilly("Commands/Give/GiveCard", `Parameters: cardNumber=${cardNumber.value}, user=${user.id}`);
const card = CardDropHelperMetadata.GetCardByCardNumber(cardNumber.value!.toString());
if (!card) {
await interaction.reply("Unable to fetch card, please try again.");
return;
}
let inventory = await Inventory.FetchOneByCardNumberAndUserId(user.id, card.card.id);
if (!inventory) {
inventory = new Inventory(user.id, card.card.id, 1);
} else {
inventory.SetQuantity(inventory.Quantity + 1);
}
await inventory.Save(Inventory, inventory);
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.get("user", true).user!;
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}`);
}
}

50
src/commands/inventory.ts Normal file
View file

@ -0,0 +1,50 @@
import { CommandInteraction, SlashCommandBuilder } from "discord.js";
import { Command } from "../type/command";
import InventoryHelper from "../helpers/InventoryHelper";
import AppLogger from "../client/appLogger";
export default class Inventory extends Command {
constructor() {
super();
this.CommandBuilder = new SlashCommandBuilder()
.setName("inventory")
.setDescription("View your inventory")
.addNumberOption(x =>
x
.setName("page")
.setDescription("The page to start with"))
.addUserOption(x =>
x
.setName("user")
.setDescription("The user to view (Defaults to yourself)"));
}
public override async execute(interaction: CommandInteraction) {
const page = interaction.options.get("page");
const userOption = interaction.options.get("user");
const user = userOption ? userOption.user! : interaction.user;
AppLogger.LogSilly("Commands/Inventory", `Parameters: page=${page?.value}, user=${user.id}`);
try {
let pageNumber = 0;
if (page && page.value) {
pageNumber = Number(page.value) - 1;
}
const embed = await InventoryHelper.GenerateInventoryPage(user.username, user.id, pageNumber);
await interaction.reply({
embeds: [ embed.embed ],
components: [ embed.row ],
});
} catch (e) {
AppLogger.LogError("Commands/Inventory", e as string);
await interaction.reply("No page for user found.");
}
}
}

View file

@ -2,38 +2,45 @@ import { CacheType, CommandInteraction, PermissionsBitField, SlashCommandBuilder
import { Command } from "../type/command";
import Config from "../database/entities/app/Config";
import CardMetadataFunction from "../Functions/CardMetadataFunction";
import AppLogger from "../client/appLogger";
export default class Resync extends Command {
constructor() {
super();
super.CommandBuilder = new SlashCommandBuilder()
.setName('resync')
.setDescription('Resync the card database')
this.CommandBuilder = new SlashCommandBuilder()
.setName("resync")
.setDescription("Resync the card database")
.setDefaultMemberPermissions(PermissionsBitField.Flags.Administrator);
}
public override async execute(interaction: CommandInteraction<CacheType>) {
if (!interaction.isChatInputCommand()) return;
const whitelistedUsers = process.env.GDRIVESYNC_WHITELIST!.split(',');
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;
}
let result = await CardMetadataFunction.Execute(true);
AppLogger.LogInfo("Commands/Resync", "Resyncing database");
const result = await CardMetadataFunction.Execute(true);
if (result) {
if (await Config.GetValue('safemode') == "true") {
await Config.SetValue('safemode', 'false');
if (await Config.GetValue("safemode") == "true") {
AppLogger.LogInfo("Commands/Resync", "Resync successful, safe mode disabled");
await Config.SetValue("safemode", "false");
await interaction.reply("Resynced database and disabled safe mode.");
return;
}
await interaction.reply("Resynced database.");
} else {
AppLogger.LogWarn("Commands/Resync", "Resync failed, safe mode activated");
await interaction.reply("Resync failed, safe mode has been activated until successful resync.");
}
}

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 ],
});
}
}

71
src/commands/series.ts Normal file
View file

@ -0,0 +1,71 @@
import { CommandInteraction, SlashCommandBuilder } from "discord.js";
import { Command } from "../type/command";
import { CoreClient } from "../client/client";
import AppLogger from "../client/appLogger";
import SeriesHelper from "../helpers/SeriesHelper";
export default class Series extends Command {
constructor() {
super();
this.CommandBuilder = new SlashCommandBuilder()
.setName("series")
.setDescription("View details on a series")
.addSubcommand(x =>
x
.setName("view")
.setDescription("View a specifiic series by id")
.addStringOption(y =>
y
.setName("id")
.setDescription("The series id")
.setRequired(true)))
.addSubcommand(x =>
x
.setName("list")
.setDescription("List all series")) as SlashCommandBuilder;
}
public override async execute(interaction: CommandInteraction) {
if (!interaction.isChatInputCommand()) return;
switch (interaction.options.getSubcommand()) {
case "view":
await this.ViewSeries(interaction);
break;
case "list":
await this.ListSeries(interaction);
break;
default:
AppLogger.LogWarn("Commands/Series", `Subcommand doesn't exist: ${interaction.options.getSubcommand()}`);
await interaction.reply("Subcommand doesn't exist.");
}
}
private async ViewSeries(interaction: CommandInteraction) {
const id = interaction.options.get("id");
AppLogger.LogSilly("Commands/Series/View", `Parameters: id=${id?.value}`);
if (!id) return;
const series = CoreClient.Cards.find(x => x.id == id.value);
if (!series) {
AppLogger.LogVerbose("Commands/Series/View", "Series not found.");
await interaction.reply("Series not found.");
return;
}
const embed = SeriesHelper.GenerateSeriesViewPage(series.id, 0);
await interaction.reply({ embeds: [ embed!.embed ], components: [ embed!.row ]});
}
private async ListSeries(interaction: CommandInteraction) {
const embed = SeriesHelper.GenerateSeriesListPage(0);
await interaction.reply({ embeds: [ embed!.embed ], components: [ embed!.row ]});
}
}

View file

@ -11,23 +11,23 @@ export default class Dropnumber extends Command {
constructor() {
super();
super.CommandBuilder = new SlashCommandBuilder()
.setName('dropnumber')
.setDescription('(TEST) Summon a specific card')
this.CommandBuilder = new SlashCommandBuilder()
.setName("dropnumber")
.setDescription("(TEST) Summon a specific card")
.addStringOption(x =>
x
.setName('cardnumber')
.setDescription('The card number to summon')
.setName("cardnumber")
.setDescription("The card number to summon")
.setRequired(true));
}
public override async execute(interaction: CommandInteraction<CacheType>) {
if (!interaction.isChatInputCommand()) return;
const cardNumber = interaction.options.get('cardnumber');
const cardNumber = interaction.options.get("cardnumber");
if (!cardNumber || !cardNumber.value) {
await interaction.reply('Card Number is required');
await interaction.reply("Card Number is required");
return;
}
@ -36,7 +36,7 @@ export default class Dropnumber extends Command {
.find(x => x.id == cardNumber.value);
if (!card) {
await interaction.reply('Card not found');
await interaction.reply("Card not found");
return;
}
@ -47,7 +47,7 @@ export default class Dropnumber extends Command {
const imageFileName = card.path.split("/").pop()!;
try {
image = readFileSync(path.join(process.cwd(), 'cards', card.path));
image = readFileSync(path.join(process.env.DATA_DIR!, "cards", card.path));
} catch {
await interaction.reply(`Unable to fetch image for card ${card.id}`);
return;
@ -78,7 +78,7 @@ export default class Dropnumber extends Command {
if (e instanceof DiscordAPIError) {
await interaction.editReply(`Unable to send next drop. Please try again, and report this if it keeps happening. Code: ${e.code}`);
} else {
await interaction.editReply(`Unable to send next drop. Please try again, and report this if it keeps happening. Code: UNKNOWN`);
await interaction.editReply("Unable to send next drop. Please try again, and report this if it keeps happening. Code: UNKNOWN");
}
}

View file

@ -12,37 +12,37 @@ export default class Droprarity extends Command {
constructor() {
super();
super.CommandBuilder = new SlashCommandBuilder()
.setName('droprarity')
.setDescription('(TEST) Summon a random card of a specific rarity')
this.CommandBuilder = new SlashCommandBuilder()
.setName("droprarity")
.setDescription("(TEST) Summon a random card of a specific rarity")
.addStringOption(x =>
x
.setName('rarity')
.setDescription('The rarity you want to summon')
.setName("rarity")
.setDescription("The rarity you want to summon")
.setRequired(true));
}
public override async execute(interaction: CommandInteraction<CacheType>) {
if (!interaction.isChatInputCommand()) return;
const rarity = interaction.options.get('rarity');
const rarity = interaction.options.get("rarity");
if (!rarity || !rarity.value) {
await interaction.reply('Rarity is required');
await interaction.reply("Rarity is required");
return;
}
const rarityType = CardRarityParse(rarity.value.toString());
if (rarityType == CardRarity.Unknown) {
await interaction.reply('Invalid rarity');
await interaction.reply("Invalid rarity");
return;
}
const card = await CardDropHelperMetadata.GetRandomCardByRarity(rarityType);
if (!card) {
await interaction.reply('Card not found');
await interaction.reply("Card not found");
return;
}
@ -50,7 +50,7 @@ export default class Droprarity extends Command {
const imageFileName = card.card.path.split("/").pop()!;
try {
image = readFileSync(path.join(process.cwd(), 'cards', card.card.path));
image = readFileSync(path.join(process.env.DATA_DIR!, "cards", card.card.path));
} catch {
await interaction.reply(`Unable to fetch image for card ${card.card.id}`);
return;
@ -81,7 +81,7 @@ export default class Droprarity extends Command {
if (e instanceof DiscordAPIError) {
await interaction.editReply(`Unable to send next drop. Please try again, and report this if it keeps happening. Code: ${e.code}`);
} else {
await interaction.editReply(`Unable to send next drop. Please try again, and report this if it keeps happening. Code: UNKNOWN`);
await interaction.editReply("Unable to send next drop. Please try again, and report this if it keeps happening. Code: UNKNOWN");
}
}

153
src/commands/trade.ts Normal file
View file

@ -0,0 +1,153 @@
import { ActionRowBuilder, ButtonBuilder, ButtonStyle, CommandInteraction, EmbedBuilder, SlashCommandBuilder } from "discord.js";
import { Command } from "../type/command";
import Inventory from "../database/entities/app/Inventory";
import { CoreClient } from "../client/client";
import EmbedColours from "../constants/EmbedColours";
import AppLogger from "../client/appLogger";
export default class Trade extends Command {
constructor() {
super();
this.CommandBuilder = new SlashCommandBuilder()
.setName("trade")
.setDescription("Initiate a trade with another user.")
.addUserOption(x =>
x
.setName("user")
.setDescription("User to trade with")
.setRequired(true))
.addStringOption(x =>
x
.setName("give")
.setDescription("Item to give")
.setRequired(true))
.addStringOption(x =>
x
.setName("receive")
.setDescription("Item to receive")
.setRequired(true));
}
public override async execute(interaction: CommandInteraction) {
const user = interaction.options.get("user", true).user!;
const give = interaction.options.get("give", true);
const receive = interaction.options.get("receive", true);
AppLogger.LogSilly("Commands/Trade", `Parameters: user=${user.id}, give=${give.value}, receive=${receive.value}`);
if (interaction.user.id == user.id) {
await interaction.reply("You can not create a trade with yourself.");
return;
}
const user1ItemEntity = await Inventory.FetchOneByCardNumberAndUserId(interaction.user.id, give.value!.toString());
const user2ItemEntity = await Inventory.FetchOneByCardNumberAndUserId(user.id, receive.value!.toString());
if (!user1ItemEntity) {
await interaction.reply("You do not have the item you are trying to trade.");
return;
}
if (!user2ItemEntity) {
await interaction.reply("The user you are trying to trade with does not have the item you are trying to trade for.");
return;
}
const user1Item = CoreClient.Cards
.flatMap(x => x.cards)
.find(x => x.id === give.value!.toString());
const user2Item = CoreClient.Cards
.flatMap(x => x.cards)
.find(x => x.id === receive.value!.toString());
if (!user1Item || !user2Item) {
await interaction.reply("One or more of the items you are trying to trade does not exist.");
return;
}
const now = new Date();
const expiry = now.setMinutes(now.getMinutes() + 15);
const tradeEmbed = new EmbedBuilder()
.setTitle("⚠️ Trade Offer ⚠️")
.setDescription(`Trade initiated between ${interaction.user.username} and ${user.username}`)
.setColor(EmbedColours.Grey)
.setImage("https://media1.tenor.com/m/KkZwKl2AQ2QAAAAd/trade-offer.gif")
.addFields([
{
name: `${interaction.user.username} Receives`,
value: `${user2Item.id}: ${user2Item.name}`,
inline: true,
},
{
name: `${user.username} Receives`,
value: `${user1Item.id}: ${user1Item.name}`,
inline: true,
},
{
name: "Expires",
value: new Date(expiry).toLocaleString(),
}
]);
const timeoutId = setTimeout(async () => this.autoDecline(interaction, interaction.user.username, user.username, user1Item.id, user2Item.id, user1Item.name, user2Item.name), 1000 * 60 * 15); // 15 minutes
const row = new ActionRowBuilder<ButtonBuilder>()
.addComponents([
new ButtonBuilder()
.setCustomId(`trade accept ${interaction.user.id} ${user.id} ${user1Item.id} ${user2Item.id} ${expiry} ${timeoutId}`)
.setLabel("Accept")
.setStyle(ButtonStyle.Success),
new ButtonBuilder()
.setCustomId(`trade decline ${interaction.user.id} ${user.id} ${user1Item.id} ${user2Item.id} ${expiry} ${timeoutId}`)
.setLabel("Decline")
.setStyle(ButtonStyle.Danger),
]);
await interaction.reply({ content: `${user}`, embeds: [ tradeEmbed ], components: [ row ] });
}
private async autoDecline(interaction: CommandInteraction, user1Username: string, user2Username: string, user1CardNumber: string, user2CardNumber: string, user1CardName: string, user2CardName: string) {
AppLogger.LogSilly("Commands/Trade/AutoDecline", `Auto declining trade between ${user1Username} and ${user2Username}`);
const tradeEmbed = new EmbedBuilder()
.setTitle("Trade Expired")
.setDescription(`Trade initiated between ${user1Username} and ${user2Username}`)
.setColor(EmbedColours.Error)
.setImage("https://media1.tenor.com/m/KkZwKl2AQ2QAAAAd/trade-offer.gif")
.addFields([
{
name: `${user1Username} Receives`,
value: `${user2CardNumber}: ${user2CardName}`,
inline: true,
},
{
name: `${user2Username} Receives`,
value: `${user1CardNumber}: ${user1CardName}`,
inline: true,
},
{
name: "Expired",
value: new Date().toLocaleString(),
}
]);
const row = new ActionRowBuilder<ButtonBuilder>()
.addComponents([
new ButtonBuilder()
.setCustomId("trade expired accept")
.setLabel("Accept")
.setStyle(ButtonStyle.Success)
.setDisabled(true),
new ButtonBuilder()
.setCustomId("trade expired declined")
.setLabel("Decline")
.setStyle(ButtonStyle.Danger)
.setDisabled(true),
]);
await interaction.editReply({ embeds: [ tradeEmbed ], components: [ row ]});
}
}

82
src/commands/view.ts Normal file
View file

@ -0,0 +1,82 @@
import { AttachmentBuilder, CommandInteraction, DiscordAPIError, SlashCommandBuilder } from "discord.js";
import { Command } from "../type/command";
import { CoreClient } from "../client/client";
import { readFileSync } from "fs";
import path from "path";
import Inventory from "../database/entities/app/Inventory";
import CardDropHelperMetadata from "../helpers/CardDropHelperMetadata";
import AppLogger from "../client/appLogger";
export default class View extends Command {
constructor() {
super();
this.CommandBuilder = new SlashCommandBuilder()
.setName("view")
.setDescription("View a specific command")
.addStringOption(x =>
x
.setName("cardnumber")
.setDescription("The card number to view")
.setRequired(true));
}
public override async execute(interaction: CommandInteraction) {
const cardNumber = interaction.options.get("cardnumber");
AppLogger.LogSilly("Commands/View", `Parameters: cardNumber=${cardNumber?.value}`);
if (!cardNumber || !cardNumber.value) {
await interaction.reply("Card number is required.");
return;
}
const card = CoreClient.Cards
.flatMap(x => x.cards)
.find(x => x.id == cardNumber.value);
if (!card) {
await interaction.reply("Card not found.");
return;
}
const series = CoreClient.Cards
.find(x => x.cards.includes(card))!;
let image: Buffer;
const imageFileName = card.path.split("/").pop()!;
try {
image = readFileSync(path.join(process.env.DATA_DIR!, "cards", card.path));
} catch {
AppLogger.LogError("Commands/View", `Unable to fetch image for card ${card.id}.`);
await interaction.reply(`Unable to fetch image for card ${card.id}.`);
return;
}
await interaction.deferReply();
const attachment = new AttachmentBuilder(image, { name: imageFileName });
const inventory = await Inventory.FetchOneByCardNumberAndUserId(interaction.user.id, card.id);
const quantityClaimed = inventory ? inventory.Quantity : 0;
const embed = CardDropHelperMetadata.GenerateDropEmbed({ card, series }, quantityClaimed, imageFileName);
try {
await interaction.editReply({
embeds: [ embed ],
files: [ attachment ],
});
} catch (e) {
AppLogger.LogError("Commands/View", `Error sending view for card ${card.id}: ${e}`);
if (e instanceof DiscordAPIError) {
await interaction.editReply(`Unable to send next drop. Please try again, and report this if it keeps happening. Code: ${e.code}.`);
} else {
await interaction.editReply("Unable to send next drop. Please try again, and report this if it keeps happening. Code: UNKNOWN.");
}
}
}
}

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

@ -11,51 +11,68 @@ export enum CardRarity {
export function CardRarityToString(rarity: CardRarity): string {
switch (rarity) {
case CardRarity.Unknown:
return "Unknown";
case CardRarity.Bronze:
return "Bronze";
case CardRarity.Silver:
return "Silver";
case CardRarity.Gold:
return "Gold";
case CardRarity.Legendary:
return "Legendary";
case CardRarity.Manga:
return "Manga";
case CardRarity.Unknown:
return "Unknown";
case CardRarity.Bronze:
return "Bronze";
case CardRarity.Silver:
return "Silver";
case CardRarity.Gold:
return "Gold";
case CardRarity.Legendary:
return "Legendary";
case CardRarity.Manga:
return "Manga";
}
}
export function CardRarityToColour(rarity: CardRarity): number {
switch (rarity) {
case CardRarity.Unknown:
return EmbedColours.Grey;
case CardRarity.Bronze:
return EmbedColours.BronzeCard;
case CardRarity.Silver:
return EmbedColours.SilverCard;
case CardRarity.Gold:
return EmbedColours.GoldCard;
case CardRarity.Legendary:
return EmbedColours.LegendaryCard;
case CardRarity.Manga:
return EmbedColours.MangaCard;
case CardRarity.Unknown:
return EmbedColours.Grey;
case CardRarity.Bronze:
return EmbedColours.BronzeCard;
case CardRarity.Silver:
return EmbedColours.SilverCard;
case CardRarity.Gold:
return EmbedColours.GoldCard;
case CardRarity.Legendary:
return EmbedColours.LegendaryCard;
case CardRarity.Manga:
return EmbedColours.MangaCard;
}
}
export function CardRarityParse(rarity: string): CardRarity {
switch (rarity.toLowerCase()) {
case "bronze":
return CardRarity.Bronze;
case "silver":
return CardRarity.Silver;
case "gold":
return CardRarity.Gold;
case "legendary":
return CardRarity.Legendary;
case "manga":
return CardRarity.Manga;
default:
return CardRarity.Unknown;
case "bronze":
return CardRarity.Bronze;
case "silver":
return CardRarity.Silver;
case "gold":
return CardRarity.Gold;
case "legendary":
return CardRarity.Legendary;
case "manga":
return CardRarity.Manga;
default:
return CardRarity.Unknown;
}
}
export function GetSacrificeAmount(rarity: CardRarity): number {
switch (rarity) {
case CardRarity.Bronze:
return 5;
case CardRarity.Silver:
return 10;
case CardRarity.Gold:
return 30;
case CardRarity.Manga:
return 40;
case CardRarity.Legendary:
return 100;
default:
return 0;
}
}

View file

@ -1,6 +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

@ -11,13 +11,13 @@ export default class AppBaseEntity {
}
@PrimaryColumn()
Id: string;
Id: string;
@Column()
WhenCreated: Date;
WhenCreated: Date;
@Column()
WhenUpdated: Date;
WhenUpdated: Date;
public async Save<T extends AppBaseEntity>(target: EntityTarget<T>, entity: DeepPartial<T>): Promise<void> {
this.WhenUpdated = new Date();
@ -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

@ -1,8 +1,10 @@
import { Environment } from "../constants/Environment";
import { ButtonEvent } from "../type/buttonEvent";
export default interface IButtonEventItem {
interface ButtonEventItem {
ButtonId: string,
Event: ButtonEvent,
Environment: Environment,
}
}
export default ButtonEventItem;

View file

@ -0,0 +1,19 @@
import { DMChannel, Guild, GuildBan, GuildMember, Message, NonThreadGuildBasedChannel, PartialGuildMember, PartialMessage } from "discord.js";
interface EventExecutors {
ChannelCreate: ((channel: NonThreadGuildBasedChannel) => void)[],
ChannelDelete: ((channel: DMChannel | NonThreadGuildBasedChannel) => void)[],
ChannelUpdate: ((channel: DMChannel | NonThreadGuildBasedChannel) => void)[],
GuildBanAdd: ((ban: GuildBan) => void)[],
GuildBanRemove: ((ban: GuildBan) => void)[],
GuildCreate: ((guild: Guild) => void)[],
GuildMemberAdd: ((member: GuildMember) => void)[],
GuildMemberRemove: ((member: GuildMember | PartialGuildMember) => void)[],
GuildMemebrUpdate: ((oldMember: GuildMember | PartialGuildMember, newMember: GuildMember) => void)[],
MessageCreate: ((message: Message<boolean>) => void)[],
MessageDelete: ((message: Message<boolean> | PartialMessage) => void)[],
MessageUpdate: ((oldMessage: Message<boolean> | PartialMessage, newMessage: Message<boolean> | PartialMessage) => void)[],
}
export default EventExecutors;

View file

@ -1,9 +1,11 @@
import { Environment } from "../constants/Environment";
import { Command } from "../type/command";
export default interface ICommandItem {
interface ICommandItem {
Name: string,
Command: Command,
Environment: Environment,
ServerId?: string,
}
}
export default ICommandItem;

View file

@ -1,9 +0,0 @@
import { Environment } from "../constants/Environment";
import { EventType } from "../constants/EventType";
export default interface IEventItem {
EventType: EventType,
ExecutionFunction: Function,
Environment: Environment,
}

View file

@ -1,4 +1,4 @@
export default interface IGDriveFolderListing {
export interface IGDriveFolderListing {
id: string,
name: string,
};
}

View file

@ -1,6 +1,6 @@
import { CardRarity } from "../constants/CardRarity";
export default interface SeriesMetadata {
export interface SeriesMetadata {
id: number,
name: string,
cards: CardMetadata[],

View file

@ -12,10 +12,10 @@ export default class Claim extends AppBaseEntity {
}
@Column()
ClaimId: string;
ClaimId: string;
@ManyToOne(() => Inventory, x => x.Claims)
Inventory: Inventory;
Inventory: Inventory;
public SetInventory(inventory: Inventory) {
this.Inventory = inventory;

View file

@ -12,10 +12,10 @@ export default class Config extends AppBaseEntity {
}
@Column()
Key: string;
Key: string;
@Column()
Value: string;
Value: string;
public SetValue(value: string) {
this.Value = value;

View file

@ -14,21 +14,27 @@ export default class Inventory extends AppBaseEntity {
}
@Column()
UserId: string;
UserId: string;
@Column()
CardNumber: string;
CardNumber: string;
@Column()
Quantity: number;
Quantity: number;
@OneToMany(() => Claim, x => x.Inventory)
Claims: Claim[];
Claims: Claim[];
public SetQuantity(quantity: number) {
this.Quantity = quantity;
}
public RemoveQuantity(amount: number) {
if (this.Quantity < amount) return;
this.Quantity -= amount;
}
public AddClaim(claim: Claim) {
this.Claims.push(claim);
}
@ -40,4 +46,12 @@ export default class Inventory extends AppBaseEntity {
return single;
}
public static async FetchAllByUserId(userId: string): Promise<Inventory[]> {
const repository = AppDataSource.getRepository(Inventory);
const all = await repository.find({ where: { UserId: userId }});
return all;
}
}

View file

@ -0,0 +1,34 @@
import { Column, Entity } from "typeorm";
import AppBaseEntity from "../../../contracts/AppBaseEntity";
@Entity()
export default class User extends AppBaseEntity {
constructor(userId: string, currency: number) {
super();
this.Id = userId;
this.Currency = currency;
}
@Column()
Currency: number;
@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

@ -1,17 +1,17 @@
import { MigrationInterface, QueryRunner } from "typeorm"
import MigrationHelper from "../../../../helpers/MigrationHelper"
import { MigrationInterface, QueryRunner } from "typeorm";
import MigrationHelper from "../../../../helpers/MigrationHelper";
export class CreateClaim1694609771821 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
MigrationHelper.Up('1694609771821-CreateClaim', '0.1.5', [
'01-CreateClaim',
'02-MoveToClaim',
'03-AlterInventory',
MigrationHelper.Up("1694609771821-CreateClaim", "0.1.5", [
"01-CreateClaim",
"02-MoveToClaim",
"03-AlterInventory",
], queryRunner);
}
public async down(queryRunner: QueryRunner): Promise<void> {
public async down(): Promise<void> {
}
}

View file

@ -1,15 +1,15 @@
import { MigrationInterface, QueryRunner } from "typeorm"
import MigrationHelper from "../../../../helpers/MigrationHelper"
import { MigrationInterface, QueryRunner } from "typeorm";
import MigrationHelper from "../../../../helpers/MigrationHelper";
export class CreateBase1693769942868 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
MigrationHelper.Up('1693769942868-CreateBase', '0.1', [
MigrationHelper.Up("1693769942868-CreateBase", "0.1", [
"01-table/Inventory",
], queryRunner);
}
public async down(queryRunner: QueryRunner): Promise<void> {
public async down(): Promise<void> {
}
}

View file

@ -1,15 +1,15 @@
import { MigrationInterface, QueryRunner } from "typeorm"
import MigrationHelper from "../../../../helpers/MigrationHelper"
import { MigrationInterface, QueryRunner } from "typeorm";
import MigrationHelper from "../../../../helpers/MigrationHelper";
export class CreateConfig1699814500650 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
MigrationHelper.Up('1699814500650-createConfig', '0.2', [
MigrationHelper.Up("1699814500650-createConfig", "0.2", [
"01-table/Config",
], queryRunner);
}
public async down(queryRunner: QueryRunner): Promise<void> {
public async down(): Promise<void> {
}
}

View file

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

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

@ -3,6 +3,7 @@ import { CardRarity, CardRarityToColour, CardRarityToString } from "../constants
import CardRarityChances from "../constants/CardRarityChances";
import { DropResult } from "../contracts/SeriesMetadata";
import { CoreClient } from "../client/client";
import AppLogger from "../client/appLogger";
export default class CardDropHelperMetadata {
public static GetRandomCard(): DropResult | undefined {
@ -23,10 +24,14 @@ export default class CardDropHelperMetadata {
const randomCard = this.GetRandomCardByRarity(cardRarity);
AppLogger.LogSilly("CardDropHelperMetadata/GetRandomCard", `Random card: ${randomCard?.card.id} ${randomCard?.card.name}`);
return randomCard;
}
public static GetRandomCardByRarity(rarity: CardRarity): DropResult | undefined {
AppLogger.LogSilly("CardDropHelperMetadata/GetRandomCardByRarity", `Parameters: rarity=${rarity}`);
const allCards = CoreClient.Cards
.flatMap(x => x.cards)
.filter(x => x.type == rarity);
@ -38,37 +43,73 @@ export default class CardDropHelperMetadata {
.find(x => x.cards.includes(card));
if (!series) {
AppLogger.LogWarn("CardDropHelperMetadata/GetRandomCardByRarity", `Series not found for card ${card.id}`);
return undefined;
}
AppLogger.LogSilly("CardDropHelperMetadata/GetRandomCardByRarity", `Random card: ${card.id} ${card.name}`);
return {
series: series,
card: card,
};
}
public static GenerateDropEmbed(drop: DropResult, quantityClaimed: Number, imageFileName: string): EmbedBuilder {
public static GetCardByCardNumber(cardNumber: string): DropResult | undefined {
AppLogger.LogSilly("CardDropHelperMetadata/GetCardByCardNumber", `Parameters: cardNumber=${cardNumber}`);
const card = CoreClient.Cards
.flatMap(x => x.cards)
.find(x => x.id == cardNumber);
const series = CoreClient.Cards
.find(x => x.cards.find(y => y.id == card?.id));
AppLogger.LogSilly("CardDropHelperMetadata/GetCardByCardNumber", `Card: ${card?.id} ${card?.name}`);
AppLogger.LogSilly("CardDropHelperMetadata/GetCardByCardNumber", `Series: ${series?.id} ${series?.name}`);
if (!card || !series) {
AppLogger.LogVerbose("CardDropHelperMetadata/GetCardByCardNumber", `Unable to find card metadata: ${cardNumber}`);
return undefined;
}
return { card, series };
}
public static GenerateDropEmbed(drop: DropResult, quantityClaimed: number, imageFileName: string, claimedBy?: string): EmbedBuilder {
AppLogger.LogSilly("CardDropHelperMetadata/GenerateDropEmbed", `Parameters: drop=${drop.card.id}, quantityClaimed=${quantityClaimed}, imageFileName=${imageFileName}`);
let description = "";
description += `Series: ${drop.series.name}\n`;
description += `Claimed: ${quantityClaimed}\n`;
if (claimedBy != null) {
description += `Claimed by: ${claimedBy}\n`;
} else {
description += "Claimed by: (UNCLAIMED)\n";
}
return new EmbedBuilder()
.setTitle(drop.card.name)
.setDescription(description)
.setFooter({ text: CardRarityToString(drop.card.type) })
.setFooter({ text: `${CardRarityToString(drop.card.type)} · ${drop.card.id}` })
.setColor(CardRarityToColour(drop.card.type))
.setImage(`attachment://${imageFileName}`);
}
public static GenerateDropButtons(drop: DropResult, claimId: string, userId: string): ActionRowBuilder<ButtonBuilder> {
public static GenerateDropButtons(drop: DropResult, claimId: string, userId: string, disabled: boolean = false): ActionRowBuilder<ButtonBuilder> {
AppLogger.LogSilly("CardDropHelperMetadata/GenerateDropButtons", `Parameters: drop=${drop.card.id}, claimId=${claimId}, userId=${userId}`);
return new ActionRowBuilder<ButtonBuilder>()
.addComponents(
new ButtonBuilder()
.setCustomId(`claim ${drop.card.id} ${claimId} ${userId}`)
.setLabel("Claim")
.setStyle(ButtonStyle.Primary),
.setStyle(ButtonStyle.Primary)
.setDisabled(disabled),
new ButtonBuilder()
.setCustomId(`reroll`)
.setCustomId("reroll")
.setLabel("Reroll")
.setStyle(ButtonStyle.Secondary));
}

View file

@ -0,0 +1,105 @@
import { ActionRowBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder } from "discord.js";
import Inventory from "../database/entities/app/Inventory";
import { CoreClient } from "../client/client";
import EmbedColours from "../constants/EmbedColours";
import { CardRarity, CardRarityToString } from "../constants/CardRarity";
import cloneDeep from "clone-deep";
import AppLogger from "../client/appLogger";
interface InventoryPage {
id: number,
name: string,
cards: InventoryPageCards[],
seriesSubpage: number,
}
interface InventoryPageCards {
id: string,
name: string,
type: CardRarity,
quantity: number,
}
export default class InventoryHelper {
public static async GenerateInventoryPage(username: string, userid: string, page: number): Promise<{ embed: EmbedBuilder, row: ActionRowBuilder<ButtonBuilder> }> {
AppLogger.LogSilly("Helpers/InventoryHelper", `Parameters: username=${username}, userid=${userid}, page=${page}`);
const cardsPerPage = 15;
const inventory = await Inventory.FetchAllByUserId(userid);
const clientCards = cloneDeep(CoreClient.Cards);
const allSeriesClaimed = clientCards
.sort((a, b) => a.id - b.id)
.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)!.Quantity > 0);
return x;
});
const pages: InventoryPage[] = [];
for (const series of allSeriesClaimed) {
const seriesCards = series.cards;
for (let i = 0; i < seriesCards.length; i+= cardsPerPage) {
const cards = series.cards.slice(i, i + cardsPerPage);
const pageCards: InventoryPageCards[] = [];
for (const card of cards) {
const item = inventory.find(x => x.CardNumber == card.id);
if (!item) {
continue;
}
pageCards.push({
id: card.id,
name: card.name,
type: card.type,
quantity: item.Quantity,
});
}
pages.push({
id: series.id,
name: series.name,
cards: pageCards,
seriesSubpage: i / cardsPerPage,
});
}
}
const currentPage = pages[page];
if (!currentPage) {
AppLogger.LogError("Helpers/InventoryHelper", "Unable to find page");
return Promise.reject("Unable to find page");
}
const embed = new EmbedBuilder()
.setTitle(username)
.setDescription(`**${currentPage.name} (${currentPage.seriesSubpage + 1})**\n${currentPage.cards.map(x => `[${x.id}] ${x.name} (${CardRarityToString(x.type)}) x${x.quantity}`).join("\n")}`)
.setFooter({ text: `Page ${page + 1} of ${pages.length}` })
.setColor(EmbedColours.Ok);
const row = new ActionRowBuilder<ButtonBuilder>()
.addComponents(
new ButtonBuilder()
.setCustomId(`inventory ${userid} ${page - 1}`)
.setLabel("Previous")
.setStyle(ButtonStyle.Primary)
.setDisabled(page == 0),
new ButtonBuilder()
.setCustomId(`inventory ${userid} ${page + 1}`)
.setLabel("Next")
.setStyle(ButtonStyle.Primary)
.setDisabled(page + 1 == pages.length));
return { embed, row };
}
}

View file

@ -3,7 +3,7 @@ import { QueryRunner } from "typeorm";
export default class MigrationHelper {
public static Up(migrationName: string, version: string, queryFiles: string[], queryRunner: QueryRunner) {
for (let path of queryFiles) {
for (const path of queryFiles) {
const query = readFileSync(`${process.cwd()}/database/${version}/${migrationName}/Up/${path}.sql`).toString();
queryRunner.query(query);
@ -11,7 +11,7 @@ export default class MigrationHelper {
}
public static Down(migrationName: string, version: string, queryFiles: string[], queryRunner: QueryRunner) {
for (let path of queryFiles) {
for (const path of queryFiles) {
const query = readFileSync(`${process.cwd()}/database/${version}/${migrationName}/Down/${path}.sql`).toString();
queryRunner.query(query);

View file

@ -0,0 +1,99 @@
import { ActionRowBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder } from "discord.js";
import AppLogger from "../client/appLogger";
import cloneDeep from "clone-deep";
import { CoreClient } from "../client/client";
import EmbedColours from "../constants/EmbedColours";
import { CardRarityToString } from "../constants/CardRarity";
export default class SeriesHelper {
public static GenerateSeriesViewPage(seriesId: number, page: number): { embed: EmbedBuilder, row: ActionRowBuilder<ButtonBuilder> } | null {
AppLogger.LogSilly("Helpers/SeriesHelper", `Parameters: seriesId=${seriesId}, page=${page}`);
const itemsPerPage = 15;
const series = cloneDeep(CoreClient.Cards)
.find(x => x.id == seriesId);
if (!series) {
AppLogger.LogVerbose("Helpers/SeriesHelper", `Unable to find series: ${seriesId}`);
return null;
}
const totalPages = Math.ceil(series.cards.length / itemsPerPage);
if (page > totalPages) {
AppLogger.LogVerbose("Helpers/SeriesHelper", `Trying to find page greater than what exists for this series. Page: ${page} but there are only ${totalPages} pages`);
return null;
}
const cardsOnPage = series.cards.splice(page * itemsPerPage, itemsPerPage);
const description = cardsOnPage
.map(x => `[${x.id}] ${x.name} ${CardRarityToString(x.type).toUpperCase()}`)
.join("\n");
const embed = new EmbedBuilder()
.setTitle(series.name)
.setColor(EmbedColours.Ok)
.setDescription(description)
.setFooter({ text: `${series.id} · ${series.cards.length} cards · Page ${page + 1} of ${totalPages}` });
const row = new ActionRowBuilder<ButtonBuilder>()
.addComponents(
new ButtonBuilder()
.setCustomId(`series view ${seriesId} ${page - 1}`)
.setLabel("Previous")
.setStyle(ButtonStyle.Primary)
.setDisabled(page == 0),
new ButtonBuilder()
.setCustomId(`series view ${seriesId} ${page + 1}`)
.setLabel("Next")
.setStyle(ButtonStyle.Primary)
.setDisabled(page + 1 > totalPages));
return { embed, row };
}
public static GenerateSeriesListPage(page: number): { embed: EmbedBuilder, row: ActionRowBuilder<ButtonBuilder> } | null {
AppLogger.LogSilly("Helpers/InventoryHelper", `Parameters: page=${page}`);
const itemsPerPage = 15;
const series = cloneDeep(CoreClient.Cards)
.sort((a, b) => a.id - b.id);
const totalPages = Math.ceil(series.length / itemsPerPage);
if (page > totalPages) {
AppLogger.LogVerbose("Helpers/SeriesHelper", `Trying to find page greater than what exists for this series. Page: ${page} but there are only ${totalPages} pages`);
return null;
}
const seriesOnPage = series.splice(page * itemsPerPage, itemsPerPage);
const description = seriesOnPage
.map(x => `[${x.id}] ${x.name}`)
.join("\n");
const embed = new EmbedBuilder()
.setTitle("Series")
.setColor(EmbedColours.Ok)
.setDescription(description)
.setFooter({ text: `${CoreClient.Cards.length} series · Page ${page + 1} of ${totalPages}` });
const row = new ActionRowBuilder<ButtonBuilder>()
.addComponents(
new ButtonBuilder()
.setCustomId(`series list ${page - 1}`)
.setLabel("Previous")
.setStyle(ButtonStyle.Primary)
.setDisabled(page == 0),
new ButtonBuilder()
.setCustomId(`series list ${page + 1}`)
.setLabel("Next")
.setStyle(ButtonStyle.Primary)
.setDisabled(page + 1 > totalPages));
return { embed, row };
}
}

View file

@ -1,7 +1,7 @@
export default class StringTools {
public static Capitalise(str: string): string {
const words = str.split(" ");
let result: string[] = [];
const result: string[] = [];
words.forEach(word => {
const firstLetter = word.substring(0, 1).toUpperCase();
@ -26,17 +26,17 @@ export default class StringTools {
public static RandomString(length: number) {
let result = "";
const characters = 'abcdefghkmnpqrstuvwxyz23456789';
const characters = "abcdefghkmnpqrstuvwxyz23456789";
const charactersLength = characters.length;
for ( var i = 0; i < length; i++ ) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
for ( let i = 0; i < length; i++ ) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
}
public static ReplaceAll(str: string, find: string, replace: string) {
return str.replace(new RegExp(find, 'g'), replace);
return str.replace(new RegExp(find, "g"), replace);
}
}

View file

@ -4,23 +4,23 @@ export default class TimeLengthInput {
public readonly value: string;
constructor(input: string) {
this.value = StringTools.ReplaceAll(input, ',', '');
this.value = StringTools.ReplaceAll(input, ",", "");
}
public GetDays(): number {
return this.GetValue('d');
return this.GetValue("d");
}
public GetHours(): number {
return this.GetValue('h');
return this.GetValue("h");
}
public GetMinutes(): number {
return this.GetValue('m');
return this.GetValue("m");
}
public GetSeconds(): number {
return this.GetValue('s');
return this.GetValue("s");
}
public GetMilliseconds(): number {
@ -106,7 +106,7 @@ export default class TimeLengthInput {
}
private GetValue(designation: string): number {
const valueSplit = this.value.split(' ');
const valueSplit = this.value.split(" ");
const desString = valueSplit.find(x => x.charAt(x.length - 1) == designation);

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

@ -1,8 +1,9 @@
import { Request, Response } from "express";
import CardMetadataFunction from "../Functions/CardMetadataFunction";
import AppLogger from "../client/appLogger";
export default async function ReloadDB(req: Request, res: Response) {
console.log('Reloading Card DB...');
AppLogger.LogInfo("Hooks/ReloadDB", "Reloading Card DB...");
await CardMetadataFunction.Execute();

View file

@ -1,10 +1,19 @@
import { CoreClient } from "./client/client";
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";
// Test Command Imports
import Dropnumber from "./commands/stage/dropnumber";
@ -12,28 +21,39 @@ import Droprarity from "./commands/stage/droprarity";
// Button Event Imports
import Claim from "./buttonEvents/Claim";
import InventoryButtonEvent from "./buttonEvents/Inventory";
import Reroll from "./buttonEvents/Reroll";
import { Environment } from "./constants/Environment";
import SacrificeButtonEvent from "./buttonEvents/Sacrifice";
import SeriesEvent from "./buttonEvents/Series";
import TradeButtonEvent from "./buttonEvents/Trade";
export default class Registry {
public static RegisterCommands() {
// Global Commands
CoreClient.RegisterCommand('about', new About());
CoreClient.RegisterCommand('drop', new Drop());
CoreClient.RegisterCommand('gdrivesync', new Gdrivesync());
CoreClient.RegisterCommand('resync', new Resync());
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());
// Test Commands
CoreClient.RegisterCommand('dropnumber', new Dropnumber(), Environment.Test);
CoreClient.RegisterCommand('droprarity', new Droprarity(), Environment.Test);
}
public static RegisterEvents() {
CoreClient.RegisterCommand("dropnumber", new Dropnumber(), Environment.Test);
CoreClient.RegisterCommand("droprarity", new Droprarity(), Environment.Test);
}
public static RegisterButtonEvents() {
CoreClient.RegisterButtonEvent('claim', new Claim());
CoreClient.RegisterButtonEvent('reroll', new Reroll());
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,19 @@
import AppLogger from "../client/appLogger";
import CardConstants from "../constants/CardConstants";
import User from "../database/entities/app/User";
export default async function GiveCurrency() {
AppLogger.LogDebug("Timers/GiveCurrency", "Giving currency to every known user");
const users = await User.FetchAll(User);
const usersFiltered = users.filter(x => x.Currency < 1000);
for (const user of usersFiltered) {
user.AddCurrency(CardConstants.TimerGiveAmount);
}
User.SaveAll(User, users);
AppLogger.LogDebug("Timers/GiveCurrency", `Successfully gave +${CardConstants.TimerGiveAmount} currency to ${usersFiltered.length} users`);
}

View file

@ -1,7 +1,5 @@
import { ButtonInteraction } from "discord.js";
export class ButtonEvent {
public execute(interaction: ButtonInteraction) {
}
export abstract class ButtonEvent {
abstract execute(interaction: ButtonInteraction): Promise<void>;
}

View file

@ -1,9 +1,8 @@
import { CommandInteraction } from "discord.js";
export class Command {
export abstract class Command {
// 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;
public execute(interaction: CommandInteraction) {
}
abstract execute(interaction: CommandInteraction): Promise<void>;
}

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

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

View file

@ -1,6 +1,7 @@
import bodyParser from "body-parser";
import express, { Application } from "express";
import ReloadDB from "./hooks/ReloadDB";
import AppLogger from "./client/appLogger";
export default class Webhooks {
private app: Application;
@ -19,12 +20,12 @@ export default class Webhooks {
}
private setupRoutes() {
this.app.post('/api/reload-db', ReloadDB);
this.app.post("/api/reload-db", ReloadDB);
}
private setupListen() {
this.app.listen(this.port, () => {
console.log(`API listening on port ${this.port}`);
AppLogger.LogInfo("Webhooks", `API listening on port ${this.port}`);
});
}
}

5952
yarn.lock Normal file

File diff suppressed because it is too large Load diff