{"id":25228905,"url":"https://github.com/chrisbouchard/discord-fate-bot","last_synced_at":"2025-10-26T06:31:17.587Z","repository":{"id":54971257,"uuid":"226176255","full_name":"chrisbouchard/discord-fate-bot","owner":"chrisbouchard","description":"Discord bot to help play the Fate role playing game","archived":false,"fork":false,"pushed_at":"2020-04-18T22:06:13.000Z","size":244,"stargazers_count":6,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-02-07T13:47:25.633Z","etag":null,"topics":["bot","discord","discord-bot","fate","fate-accelerated","fate-core","rpg","rpg-tool"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chrisbouchard.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-12-05T19:41:41.000Z","updated_at":"2024-05-13T13:48:20.000Z","dependencies_parsed_at":"2022-08-14T07:50:24.079Z","dependency_job_id":null,"html_url":"https://github.com/chrisbouchard/discord-fate-bot","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrisbouchard%2Fdiscord-fate-bot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrisbouchard%2Fdiscord-fate-bot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrisbouchard%2Fdiscord-fate-bot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrisbouchard%2Fdiscord-fate-bot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chrisbouchard","download_url":"https://codeload.github.com/chrisbouchard/discord-fate-bot/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238281050,"owners_count":19446078,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bot","discord","discord-bot","fate","fate-accelerated","fate-core","rpg","rpg-tool"],"created_at":"2025-02-11T10:46:18.216Z","updated_at":"2025-10-26T06:31:17.249Z","avatar_url":"https://github.com/chrisbouchard.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Discord Fate Bot\n\n[![CircleCI][circleci-dfb-svg]][circleci-dfb]\n[![Docker][shieldsio-docker-dfb]][docker-dfb]\n[![Docker App][shieldsio-docker-dfb-app]][docker-dfb-app]\n[![PyPI Version][shieldsio-pypi-dfb]][pypi-dfb]\n[![PyPI Python][shieldsio-python-dfb]][pypi-dfb]\n\nA [Discord][discordapp] bot to help play the [Fate roleplaying game][fate-rpg].\n\n[discordapp]: https://discordapp.com/\n[fate-rpg]: https://www.evilhat.com/home/fate-core/\n\n[circleci-dfb]: https://circleci.com/gh/chrisbouchard/discord-fate-bot\n[circleci-dfb-svg]: https://circleci.com/gh/chrisbouchard/discord-fate-bot.svg?style=svg\n[docker-dfb]: https://hub.docker.com/repository/docker/chrisbouchard/discord-fate-bot\n[docker-dfb-app]: https://hub.docker.com/repository/docker/chrisbouchard/discord-fate-bot-app\n[pypi-dfb]: https://pypi.org/project/discord-fate-bot/\n[shieldsio-docker-dfb]: https://img.shields.io/docker/v/chrisbouchard/discord-fate-bot?sort=semver\u0026label=docker\n[shieldsio-docker-dfb-app]: https://img.shields.io/docker/v/chrisbouchard/discord-fate-bot-app?sort=semver\u0026label=docker%20app\n[shieldsio-pypi-dfb]: https://img.shields.io/pypi/v/discord-fate-bot\n[shieldsio-python-dfb]: https://img.shields.io/pypi/pyversions/discord-fate-bot\n\n\n## Commands\n\nOnce Discord Fate Bot is invited to a server, it will listen in text channels\nfor commands and reply. All commands start with `!`.\n\n### `!roll`\n\nRoll four Fate dice, with modifiers, optionally against a static opposition.\nThis command has the following forms.\n\n* `!roll` \u0026mdash; Simply roll four Fate dice and see the result\n* `!roll [+|-]MOD...` \u0026mdash; Roll with a modifier. The `+` or `-` is required.\n  Multiple modifiers may be given, separated by spaces.\n    * Example: `!roll +5 -2` to roll with an effective +3 modifier.\n* `!roll MODIFIERS vs OPPOSITION` \u0026mdash; Roll against a static opposition\n  amount. The result will be one of: fail, tie, succeed, or succeed with style.\n    * Example: `!roll +2 vs 3`\n\n### `!scene`\n\nStart a scene in the current channel. Each channel can have one scene active,\nwhich can be used to track situation aspects. The message describing the\ncurrent scene will automatically be pinned (and unpinned when the scene ends).\n\n* `!scene [DESCRIPTION]` \u0026mdash; Start a new scene in the current channel. The\n  entire rest of the message will be used as the description. If a scene is\n  already active, it will be ended automatically.\n    * Example: `!scene Warehouse Five`\n\n* `!scene end` \u0026mdash; End the current scene.\n\n### `!aspect`\n\nAdd or manage aspects in the current scene. There must be an active scene in\nthe current channel to use these commands. Aspects are automatically added to\nthe pinned scene message.\n\nEvery aspect is given an ID \u0026mdash; a unique number within the scene \u0026mdash;\nwhich is used to refer to the aspect after creation (for example, to remove\nit).\n\n* `!aspect NAME` \u0026mdash; Add a new aspect to the current scene. The rest of the\n  line will be used the aspect name.\n    * Example: `!aspect Darkness of night`\n* `!aspect remove ID...` \u0026mdash; Remove one or more aspects from the scene.\n* `!aspect rename ID [NAME]` \u0026mdash; Rename an existing aspect. The rest of the\n  line will be used as the new aspect name.\n    * Example: `!aspect modify 2 New aspect name`\n\n### `!boost`\n\nAdd or manage boosts in the current scene. All the rules from `!aspect` apply\nfor this command as well. Note that boosts are still aspects, so they can be\nmanipulated with `!aspect remove` and `!aspect rename`.\n\n* `!boost NAME` \u0026mdash; Add a new boost to the current scene. The rest of the\n  line will be used the aspect name. Boosts are always created with one free\n  invoke.\n    * Example: `!boost Slippery banana peel`\n* `!boost upgrade ID [NAME]` \u0026mdash; Upgrade a boost to a full aspect,\n  optionally renaming it in the process. The rest of the line, if any, will be\n  used the new aspect name.\n* `!boost downgrade ID [NAME]` \u0026mdash; Upgrade an existing aspect to a boost,\n  optionally renaming it in the process. The rest of the line, if any, will be\n  used the new aspect name.\n\n### `!invoke`\n\n* `!invoke ID` \u0026mdash; Decrease the number of remaining free invokes for the\n  specified aspect.\n    * Example: `!invoke 3` to remove a free invoke from Aspect \\#3.\n    * **TODO:** If and when we introduce a Fate Point tracker, we will likely\n      have this command tie in, so that an aspect can be invoked for a Fate\n      Point.\n* `!invoke add [[+|-]AMOUNT] ID` \u0026mdash; Add (or remove) a number of free\n  invokes from the specified aspect. The amount is optional (the default is\n  `+1`), but it must start with `+` or `-`.\n    * Example: `!invoke add 2` to add one free invoke to Aspect \\#2.\n    * Example: `!invoke add +2 1` to add two free invokes to Aspect \\#1.\n    * Example: `!invoke add -1 3` to _remove_ one free invoke from Aspect \\#3.\n\n### Future Commands\n\nI plan to add commands to manage a turn order, and possibly to track fate\npoints. Beyond that, I may add facilities to track PCs and NPCs, though Discord\ntext channels may not be the most convenient interface to manage those.\n\n\n## Inviting the Bot\n\nThere isn't currently a public instance of Discord Fate Bot available for\ninvite. If you host your own copy, the bot will log an invite URL when it\nconnects to Discord. Currently, the bot will ask for the following Discord\npermissions.\n\n* Add reactions\n    * To leave a :+1: once it has processed a message.\n* Manage messages\n    * To pin and unpin the scene message.\n* Read message history\n    * Not currently used, but I have a half-thought that there could be a\n      feature to recover scenes from message history if the database is\n      out-of-sync with the channel.\n* Read messages\n    * To read commands.\n* Send messages\n    * To reply with results.\n\nThis list may grow and change while the bot is in development, but I'll try to\nfreeze it once I release a stable public version.\n\n\n## Installing\n\n### Installing in Docker Swarm as an App\n\nThis is the approach I'm currently using. [Docker App][docker-app] is currently\nan experimental plugin for Docker for deploying application bundles in Docker\nSwarm.  The bundles are uploaded as images right in Docker Hub, and the service\nimages are baked right into the application bundle.\n\nThe app for Discord Fate Bot defines two services, one for the bot itself, and\none for a MongoDB database. The latter will only be replicated to the swarm\nmanager, and the database will be saved in a Docker volume.\n\nTo install as an App, first [install Docker App][docker-app-install]. It's a\nCLI extension, so you just need it on the machine where you're managing the\nswarm.\n\nNext, set up the necessary secrets to run the app.\n\n```console\n$ docker secret create discord-fate-bot-token -\n$ docker secret create discord-fate-bot-mongo-password -\n```\n\nEach command will wait for you to type input on standard input (end with Ctrl-D\non a new line). Alternately, you can pipe in the secret or supply a filename in\nplace of `-`.\n\nFinally, install the app itself.\n\n```console\n$ docker app install chrisbouchard/discord-fate-bot-app\nCreating network discord-fate-bot-app_internal\nCreating service discord-fate-bot-app_app\nCreating service discord-fate-bot-app_mongo\nApplication \"discord-fate-bot-app\" installed on context \"default\"\n```\n\nUsing the default name, the services created will be `discord-fate-bot-app_app`\nfor the bot service, and `discord-fate-bot-app_mongo` for the MongoDB service.\nYou can use the standard Docker Swarm tools to manage them, e.g., `docker\nservice logs` to view logs.\n\nWhen a new version of Discord Fate Bot is released, you can update your\napplication to the latest version as so.\n\n```console\n$ docker app upgrade discord-fate-bot-app --app-name=chrisbouchard/discord-fate-bot-app\nUpdating service discord-fate-bot-app_app (id: ...)\nUpdating service discord-fate-bot-app_mongo (id: ...)\nApplication \"discord-fate-bot-app\" upgraded on context \"default\"\n```\n\n[docker-app]: https://github.com/docker/app\n[docker-app-install]: https://github.com/docker/app#installation\n\n### Installing from PyPI\n\nDiscord Fate Bot is also available [on PyPI][pypi-dfb].\n\n```console\n$ pip install discord-fate-bot\n$ discord-fate-bot\n```\n\nMake sure to configure your environment variables to hook up to Discord and\nyour Mongo database (see below).\n\n### Installing from Source\n\nI don't necessarily recommend this for production, but you can check out the\nproject locally and install in a virtual environment.\n\nMake sure you have at least Python 3.7 installed. You'll also need to\n[install Poetry][install-poetry], which we use for dependency management\nand packaging.\n\n```console\n$ git checkout https://github.com/chrisbouchard/discord-fate-bot.git\n$ cd discord-fate-bot\n$ poetry install\n$ poetry run discord-fate-bot\n```\n\nMake sure to configure your environment variables to hook up to Discord and\nyour Mongo database (see below).\n\n[install-poetry]: https://python-poetry.org/docs/#installation\n\n\n## Configuring\n\nDiscord Fate Bot looks for the following environment variables on start-up.\n\n* `DFB_BOT_TOKEN` \u0026mdash; The Discord authentication token for the bot account.\n    * Mutually exclusive with `DFB_BOT_TOKEN_FILE`.\n* `DFB_BOT_TOKEN_FILE` \u0026mdash; The path to a file _containing_ the\n  authentication token.\n    * Mutually exclusive with `DFB_BOT_TOKEN`.\n* `DFB_LOG_CONFIG_FILE` \u0026mdash; _(Optional)_ The path to a Python log config\n  file. See the [Python documentation][python-logging-config] for a description\n  of the file format.\n* `DFB_MONGO_CONNECTION_URL` \u0026mdash; The MongoDB connection URL.\n* `DFB_MONGO_PASSWORD` \u0026mdash; The password for the Mongo DB connection.\n    * Mutually exclusive with `DFB_MONGO_PASSWORD_FILE`.\n* `DFB_MONGO_PASSWORD_FILE` \u0026mdash; The path to a file _containing_ the\n  password for the Mongo DB connection.\n    * Mutually exclusive with `DFB_MONGO_PASSWORD`.\n\n[python-logging-config]: https://docs.python.org/3/library/logging.config.html#configuration-file-format\n\n**Note:** For variables that have a `*_FILE` pair, the direct version is\nprovided as a convenience, e.g., for development. I subscribe to the school of\nthought that it's best not to store production secrets in environment variables\nif at all avoidable. Our Docker Stack definition uses Secrets to share the\nDiscord token and Mongo password into the services.\n\n\n## Architecture\n\nDiscord Fate Bot is written in Python, mostly based on the awesome\n[Discord.py][discord-py] library. We use [MongoDB][mongo-db] for long-term\nstorage when necessary (e.g., for scenes and aspects).\n\n[discord-py]: https://github.com/Rapptz/discord.py\n[mongo-db]: https://www.mongodb.com/\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchrisbouchard%2Fdiscord-fate-bot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchrisbouchard%2Fdiscord-fate-bot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchrisbouchard%2Fdiscord-fate-bot/lists"}