Coder Social home page Coder Social logo

dawnbrandbots / bastion-bot Goto Github PK

View Code? Open in Web Editor NEW
10.0 4.0 11.0 5.55 MB

A Discord bot for displaying information about Yu-Gi-Oh! cards in all official languages.

Home Page: https://discord.com/application-directory/383854640694820865

License: GNU Affero General Public License v3.0

TypeScript 99.68% Dockerfile 0.32%
discord discord-bot discord-js discordjs yugioh yu-gi-oh typescript ts chinese french german italian japanese korean portuguese spanish bot docker master-duel masterduel

bastion-bot's Introduction

Bastion Invite to Discord

Bastion avatar

English 한국어 日本語 简体中文 繁體中文 Português Español Français Deutsch Italiano

A free and open-source Discord bot for looking up cards and other useful information about the Yu-Gi-Oh! Trading Card Game, Official Card Game, Rush Duel, and Master Duel video game.

Get started with searching for cards using <> in your messages! For Slash Command documentation, look in docs/commands. For everything else, please refer to the old Bastion Classic repository.

Thanks to YGOPRODECK for sponsoring Bastion. Prices provided by Bastion are YGOPRODECK affiliate links.

Card images and most card data are sourced from Yugipedia via YAML Yugi.

Invite to Discord   Discord App Directory

Discord permissions

Please make sure you use an invite link that automatically grants the following permissions.

  • Create commands in a server
  • Send Messages
  • Send Messages in Threads
  • Embed Links: Bastion displays card information in a Discord rich embed.
  • Attach Files: Bastion attaches card images for trivia.
  • Read Message History: Bastion replies to messages that request card search.
  • Use External Emojis: Bastion uses certain emojis for Yu-Gi-Oh icons in its embeds.
  • Add Reactions: Bastion uses "reaction buttons" for advanced control of outputs.

If you do not want Bastion to be used in a channel, deny it the View Channel permission. Otherwise, all of the above permissions must be granted to Bastion in each channel it is available in for it to work correctly.

If you do not want Slash Commands to be used in a channel, this can be managed per command in the Integrations tab of your server settings. Alternatively, you can blanket deny the Use Application Commands permission for the individuals or roles in question, but this will apply to all bots.

Support server

Support server invite

Contributing

codecov Continuous integration and deployment CodeQL Contract tests

Bastion is written in TypeScript. It targets Node.js 20+ and can be run with or without Docker. It uses Discord.js to talk to Discord.

Please use Australian English spellings.

Translations

Bastion intends to be fully localised to all regions with official Yu-Gi-Oh! releases. Translation work is incomplete and we appreciate any translator help. The localisation files are in the translations directory; for more information, please see the documentation for translators.

Privacy

See PRIVACY.md for Bastion's Privacy Policy.

Licence

Copyright © 2021–2024 Luna Brand, Kevin Lu. See COPYING for more details.

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>.

bastion-bot's People

Contributors

alphakretin avatar dependabot[bot] avatar ice-pendragon avatar jsy1728 avatar kevinlul avatar larry126 avatar myyourcaramel avatar naimsantos avatar timolob avatar xyj-3 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

bastion-bot's Issues

Create a news feed of user-facing bot updates

Possible options:

  1. CHANGELOG or NEWS file in the repository, like the one formerly maintained for Emcee
  2. The above, but also with an additional RSS or Atom feed. This could be manually maintained XML or somehow automatically generated. This can be connected to a Discord announcements channel via MonitoRSS
  3. A GitHub Pages site, with "blog posts" automatically updating an RSS or Atom feed. MonitoRSS integration works the same.
  4. GitHub Releases, which have an associated Atom feed.

/deck milestones

/deck

  • Port overflow handling from Emcee (highlander-style decks particularly affected). Can release initially at this stage. (#27)
  • Play around with the labels for ratios to improve appearance and aid localization for the inline layout
  • Localization: show the card names in the user's selected language
  • Localization: switch the labels to the corresponding language. We should look into appropriate i18n packages instead of handrolling first.
  • Attach processed YDK to embed like Emcee (where possible, if ephemerals don't support this).

Attachments

Slash Commands don't support attachments, so to replicate the other function of the old .deck:

  • Process any YDK that comes in through DMs like /deck (maybe the message can optionally state the language and style?)
  • Process any YDK that is attached to a bot mention, since we will still see those without the Message Intent. Same parameter idea as DMs.

Rush Duel Artworks

Any plans to make Rush Duels artworks avaliable to find with the /art command? Atleast the ones that are available from the datamines of the old switch game, since I know these can be pretty annoying to crop.

The next Rush Duel switch game is coming on the first of December too, and it's liable to get datamined for lots of clean artwork of the cards.

<> card search behaviour when missing reaction permissions

This is also a fairly common error logged at the warn level, but unlike #186, it is not detrimental to bot function. Some courses of action:

  1. Edit the embed to note that Bastion is missing permissions to perform the reaction.
  2. Check for reaction permissions before attempting, if it does not cost as much overhead as actually performing the action.
  3. Edit the promise rejection handlers to only log at info level if the error is Missing Permissions.

Crash after 2023-01-29T05:05:44.587Z and before 2023-01-29T05:06:10.706Z

/app/node_modules/http2-wrapper/source/agent.js:396
                                                        const error = new Error('Session closed without receiving a SETTINGS frame');
                                                                      ^
Error: Session closed without receiving a SETTINGS frame
    at ClientHttp2Session.<anonymous> (/app/node_modules/http2-wrapper/source/agent.js:396:22)
    at Object.onceWrapper (node:events:627:28)
    at ClientHttp2Session.emit (node:events:513:28)
    at emitClose (node:internal/http2/core:1086:8)
    at TLSSocket.<anonymous> (node:internal/http2/core:1113:7)
    at TLSSocket.emit (node:events:525:35)
    at node:net:320:12
    at TCP.done (node:_tls_wrap:588:7)
Emitted 'error' event on ClientRequest instance at:
    at ClientRequest.flushHeaders (/app/node_modules/http2-wrapper/source/client-request.js:363:10) {
  code: 'HTTP2WRAPPER_NOSETTINGS'
}
Node.js v18.13.0

Implement <>

This will partially succeed the classic embed view. Functions like a basic /search, but multiple may be triggered at once from a message (old limit: 3).

  • Check what servers have fullBrackets configured, and then determine the priority for administrative /bracket left and /bracket right commands.
  • Choose a delimiter for specifying inputLanguage and resultLanguage. Old Bastion used trailing ,en,ja, for example.

Should only trigger for search strings not containing (. The left parenthesis does not appear in card names. These will still be routed to the old bot for various unofficial cards, to allow for partial rollout of the new bot on official cards. This heuristic does catch a lot, but not some cards in this category, like C/C/C or Cookpal, which originally would not need to have (anime) included for the search to resolve.

/search: message component buttons below card embed

We can have up to five buttons attached to the search response. After #145, we will be able to use builders to create these.

Let's determine what the five buttons should be here (e.g. next match, report bad result, feedback, more prominent hyperlink) and implement. Scope restricted to /search (and #152) because some buttons may not make sense for /random.

Display Pendulum cards with details split between two embeds

This idea came up while we were discussing how to categorise different properties of cards based on what we need each bit of information for. We decided we'd like to include the Spell Green colouration for Pendulums, but Discord Embeds only support one colour. However, messages can support two embeds and Pendulum monsters have about twice as much information as most to convey. This turned out to be quite simple to implement in a quick test - the embeds field in the options parameter to interactions.reply is an array and two embeds passed do show up in order in the same message, so if we colour the first in Effect Orange and the second in Spell Green it convincingly mimics the appearance of a Pendulum monster.

Shard null: SqliteError: UNIQUE constraint failed: searches.message, searches.query

Using <> to search for the same token twice in one message causes metrics logging to fail (and the result to be sent twice). Interestingly, this exception is caught by discord.js itself and emitted from the bot instance's "error" event.

Should be resolved by filtering the input array pre-slicing for uniqueness, such as via Set.

Internal logs:

[RESOLVED] ⚠️Production outage: bot ceased receiving events from Discord after about 2022-10-13 15:20 UTC

Resolved 2022-10-14T01:42:30.144Z by container reboot

After a search at 2022-10-13T15:20:03.012Z and a shard reconnect at 2022-10-13T15:24:38.261Z, Bastion's new instance ceased receiving events from the Discord gateway for over 10 hours before it was noticed by developers. The cause is unclear as the program remained running. Ping response, Slash Commands, and new <> search were down during this time.

Zero-downtime deployments

A new release to the live Bastion could cause up to a minute of downtime, rounding up, due to stopping the bot process and then starting up a new process, which reconnects shard-by-shard to the Discord gateway to not be rate-limited. To have no downtime, deployments need to start up the new process first, make sure that no duplicate responses happen in the deployment period while there are two processes running, then stop the old process once the new process has connected all shards to the gateway. Two things must be implemented for this to happen: container start before stop and a lock manager.

Container start before stop

In Swarm, this is configured as deploy.update_config.order: start-first (docs). This is not supported by Compose v1 or v2. Therefore, to use this, production must be switched to a single-node Swarm. (Not yet at the scale where additional benefits are reaped from separating shards into their own processes.)

A pure Compose solution could be to use different project names with each deployment, as long as previous project names are kept track of so the old stack can be taken down.

Lock manager

Since Bastion is not yet at the scale for sharding across multiple hosts, the fastest solution should be write-ahead-log SQLite. Before processing a message or interaction, attempt to INSERT the snowflake into a table. Continue only if this succeeds, as we have the lock. If not, a different process has taken the lock. In the general case, this kind of overhead could help with Discord eventual consistency, though this has never been a problem in practice (receiving an event N times). This overhead could also be limited to the deployment window, being toggled upon receiving a certain Unix signal.

Caveats

VM memory demands increase since it must support two bot Node.js containers running during the deployment window. The addition of <> card search has already increased memory demands.

In general (not just the zero-downtime case), how button timeouts behave across a redeployment or a bot restart should be considered.

[RESOLVED] ⚠️Production outage: bot ceased receiving events from Discord after about 2022-10-17 03:19 UTC

Similar incident #199: another 10-hour gateway silence from Discord

Resolved 2022-10-17T13:25:13.970Z by container reboot

Last search: 2022-10-17T03:19:23.459Z
Last events: shard reconnect 2022-10-17T03:41:00.661Z + shard reconnect 2022-10-17T13:24:29.089Z immediately before attempted reboot

Bastion's new instance ceased receiving events from the Discord gateway for 10 hours again. The cause is unclear as the program remained running. Ping response, Slash Commands, and new <> search were down during this time. I've reached out to Discord Developer Support

Choosing a localization system

gettext: https://www.npmjs.com/package/node-gettext, https://github.com/smhg/gettext-parser, something to generate POTs
https://github.com/messageformat/Jed (another gettext)
messageformat: https://github.com/messageformat/messageformat custom system, doesn't seem too relevant
Airbnb Polyglot: https://www.npmjs.com/package/node-polyglot
https://www.npmjs.com/package/globalize
https://www.npmjs.com/package/i18n, seems to target express
https://www.npmjs.com/package/i18next, most popular, but is key-based
https://www.npmjs.com/package/y18n, dependency of yargs and only targets CLI so concurrent commands may clobber each other

Incorrect embed colour for Normal Monsters without modern prints

Colour is orange (Main Deck non-Ritual Effect) instead of yellow due to the lack of / Normal in the typeline. Logic in card.ts:createCardEmbed where it calls setColor needs updating, maybe pulling it out of the function to do unit testing.

Examples:

  • Angel Trumpeter
  • Dark Magician, Arcana print

Non-Bastion solution is for yaml-yugi to merge with official card database scrapes for updated type lines even without modern prints.

[RESOLVED] ⚠️Production outage (partial): bot ceased receiving events for certain servers from Discord after about 2022-12-14 11:01 UTC

Resolved 2022-12-14T12:27:11.230Z by container reboot.

Certain shards disconnected from the Discord gateway and either failed to reconnect, or Discord ceased sending events for those shards to the bot. This resulted in a partial outage for about ~1.5 hours until operator intervention. Some servers would be affected and others would not be, depending on the shard they were assigned. Shard 0 is the only one that was certainly not affected by this, which includes direct messages.

Log excerpt:

2022-12-14T11:00:06.776Z bot:info:abdeploy Updating from /var/local/bastion/abdeploy.json
2022-12-14T11:00:06.777Z bot:info:abdeploy Read 2 entries
USER SEARCHES
2022-12-14T11:01:00.760Z bot:info:events Shard 1 reconnecting
2022-12-14T11:01:00.945Z bot:info:events Shard 1 resumed: 1 events replayed
2022-12-14T11:01:05.761Z bot:info:events Shard 1 reconnecting
2022-12-14T11:01:25.709Z bot:info:events Shard 5 reconnecting
2022-12-14T11:01:25.971Z bot:info:events Shard 5 resumed: 38 events replayed
2022-12-14T11:01:30.711Z bot:info:events Shard 5 reconnecting
2022-12-14T11:02:18.611Z bot:info:events Shard 4 reconnecting
2022-12-14T11:02:22.038Z bot:info:events Shard 6 reconnecting
2022-12-14T11:02:24.778Z bot:notify:events Shard 4 ready
2022-12-14T11:02:27.827Z bot:notify:events Shard 6 ready
2022-12-14T11:02:43.612Z bot:info:events Shard 4 reconnecting
2022-12-14T11:02:47.039Z bot:info:events Shard 6 reconnecting
2022-12-14T11:03:05.482Z bot:info:events Shard 2 reconnecting
USER SEARCHES
2022-12-14T12:26:21.141Z OPERATOR ATTEMPTS CONTAINER REBOOT

Price information

Need to find new data sources for card prices, including our own caching if necessary to improve latency. Known options:

  • https://yugiohprices.com/ (old Bastion)
  • YGOPRODECK API
  • TCGPlayer
  • CardMarket
  • CoolStuffInc
  • eBay
  • Amazon
  • Troll and Toad
  • Poke Order
  • Card Central
  • Ideal 808
  • Alter Reality Games
  • CoreTCG

use code AlphaKretin5 to ????

<> card search behaviour when missing message permissions

This is a common error when attempting to use <> card search and results from Bastion having permission to view a channel but not send messages in it. A rarer case comes from not having permission to read message history, which is required to use replies.

Old Bastion simply ignored these, but new Bastion logs these. I think we should take steps to ensure proper configuration and use by users. In this case, the correct method to not have <> card search in a channel is to deny Bastion permission to view a channel, and just that permission. When missing permissions, Bastion could instead send the results to the requester via direct message (if not blocked), with an additional explainer message informing them of the incorrect permissions and steps for a server admin to rectify.

Internal log examples:

Advanced search

This feature succeeds old Bastion's .match and .search commands. Documentation for old filter syntax.

  • Explore how filters may be structured with Slash Command parameters beyond just a single argument
  • Mock up a more user-friendly approach using Message Components, if possible.

The backend can support SQL now, so single-argument commands could just take the WHERE clause of a query.

Relevant old issues:

/deck: support fake passwords

This needs fake passwords to be exposed in the backend API and queryable. This also needs to include alternative artworks somehow, whether implemented in the database system (DawnbrandBots/yaml-yugi#1) or a lazy within-10 fake password interval check.

With this, /deck will exceed the old .deck and replace it.

Bot: assess whether id, stats, effect are necessary

This is a discussion rather than an immediate code issue.

My initial thoughts are that I'm happy to cut stats and effect, they saw little use and embeds mean they don't save a ton of space which was the initial use-case. id is a bit more useful for a lightweight conversion between password and name, but there might be a more appropriate avenue for that now especially with the kid complicating matters.

Remaining Rush Duel tasks

  • Should localisations for Fusion monster races not in the OCG (e.g. Cyborg) be managed in Bastion translations or as collected data?
    A: As translations. Galaxy is not a Fusion race. Konami stopped adding Fusion races after the five debuting across two packs two years ago. Not all translations are even available from Yugipedia.
  • Maximum type should be in translations
  • Should the Japanese translations keep Level/ATK/DEF in English since they are printed on the cards in English?
    A: No need to change the UI. Modern OCG cards already say ATK/DEF in English anyway.
  • Spell/Trap properties should be represented as "Spell/Continuous" instead of "Continuous Spell" because that is how they are printed on these cards.
    A: No need to change the UI. Card text in Rush Duel languages still refer to "Continuous Spell" and similar.
  • undefined icon (below) #318
  • #337

Configuring localization: /locale

Discord has added locale fields to interactions. This is supported in Discord.js as of 13.6. How we might use this information in Bastion:

Text output (labels and card text) from Bastion can fall back to the per-user locale in direct messages or the per-server guildLocale in servers as a default, instead of always requiring a locale parameter. We do not use the user-specific locale in servers as the results may be public and thus leak the user's default language setting, assuming it isn't already leaked from other sources. The latter is only available for configuration in community servers and affects the whole server, so additionally:

Add a /locale command to show the current configuration for the channel. It can support arguments to configure overrides. In direct messages, this overrides the user's Discord locale setting. In servers, this can configure the language for the whole server (overriding the community server setting if present), or for this channel (overriding any server-wide settings).

SqliteError: NOT NULL constraint failed: commands.channel

In exceptionally rare cases, it seems a ChatInputCommandInteraction may come with no channel subobject. I'm not sure on how this even happens (maybe certain cases of command use in channels where Bastion does not have View Channel?)

Should be resolved by using interaction.channelId instead in Metrics#writeCommand.

Internal logs:

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.