{"id":39657553,"url":"https://github.com/emojirades/emojirades","last_synced_at":"2026-02-20T02:08:40.351Z","repository":{"id":40425374,"uuid":"109969099","full_name":"emojirades/emojirades","owner":"emojirades","description":"Slack bot that runs the emojirades game!","archived":false,"fork":false,"pushed_at":"2026-01-18T06:33:09.000Z","size":587,"stargazers_count":2,"open_issues_count":16,"forks_count":3,"subscribers_count":3,"default_branch":"master","last_synced_at":"2026-01-18T16:44:24.934Z","etag":null,"topics":["bot","emojirades","emojirades-game","python","slack"],"latest_commit_sha":null,"homepage":"https://emojirades.io","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/emojirades.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2017-11-08T11:48:52.000Z","updated_at":"2026-01-18T06:33:11.000Z","dependencies_parsed_at":"2023-10-22T00:26:47.732Z","dependency_job_id":"97552a3d-4a93-4829-ba13-57f2f8dd1025","html_url":"https://github.com/emojirades/emojirades","commit_stats":{"total_commits":399,"total_committers":11,"mean_commits":36.27272727272727,"dds":0.6115288220551378,"last_synced_commit":"ddc913727cdcfb103dc7d71ccfff96d0bcb3c67a"},"previous_names":[],"tags_count":112,"template":false,"template_full_name":null,"purl":"pkg:github/emojirades/emojirades","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emojirades%2Femojirades","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emojirades%2Femojirades/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emojirades%2Femojirades/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emojirades%2Femojirades/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/emojirades","download_url":"https://codeload.github.com/emojirades/emojirades/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emojirades%2Femojirades/sbom","scorecard":{"id":376105,"data":{"date":"2025-08-11","repo":{"name":"github.com/emojirades/emojirades","commit":"b032f43d3c936aebc3226af1d9b544b202ebde9d"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.8,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/10 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/ci.yml:1","Warn: no topLevel permission defined: .github/workflows/release.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: GNU Affero General Public License v3.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Packaging","score":10,"reason":"packaging workflow detected","details":["Info: Project packages its releases by way of GitHub Actions.: .github/workflows/release.yml:39"],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:47: update your workflow using https://app.stepsecurity.io/secureworkflow/emojirades/emojirades/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:50: update your workflow using https://app.stepsecurity.io/secureworkflow/emojirades/emojirades/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/emojirades/emojirades/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/emojirades/emojirades/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/emojirades/emojirades/release.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:27: update your workflow using https://app.stepsecurity.io/secureworkflow/emojirades/emojirades/release.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:46: update your workflow using https://app.stepsecurity.io/secureworkflow/emojirades/emojirades/release.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:48: update your workflow using https://app.stepsecurity.io/secureworkflow/emojirades/emojirades/release.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:59: update your workflow using https://app.stepsecurity.io/secureworkflow/emojirades/emojirades/release.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:71: update your workflow using https://app.stepsecurity.io/secureworkflow/emojirades/emojirades/release.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:80: update your workflow using https://app.stepsecurity.io/secureworkflow/emojirades/emojirades/release.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:93: update your workflow using https://app.stepsecurity.io/secureworkflow/emojirades/emojirades/release.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:96: update your workflow using https://app.stepsecurity.io/secureworkflow/emojirades/emojirades/release.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:99: update your workflow using https://app.stepsecurity.io/secureworkflow/emojirades/emojirades/release.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:102: update your workflow using https://app.stepsecurity.io/secureworkflow/emojirades/emojirades/release.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:108: update your workflow using https://app.stepsecurity.io/secureworkflow/emojirades/emojirades/release.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:116: update your workflow using https://app.stepsecurity.io/secureworkflow/emojirades/emojirades/release.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:124: update your workflow using https://app.stepsecurity.io/secureworkflow/emojirades/emojirades/release.yml/master?enable=pin","Warn: containerImage not pinned by hash: Dockerfile:1: pin your Docker image by updating python:3.13-bookworm to python:3.13-bookworm@sha256:1bfefad1a8bb66c1573378716c3bf18a59f438fe8a032d7fab43124f6f7ce9c6","Warn: containerImage not pinned by hash: Dockerfile:13: pin your Docker image by updating python:3.13-bookworm to python:3.13-bookworm@sha256:1bfefad1a8bb66c1573378716c3bf18a59f438fe8a032d7fab43124f6f7ce9c6","Warn: pipCommand not pinned by hash: Dockerfile:9","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:55","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:56","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:23","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:24","Warn: pipCommand not pinned by hash: .github/workflows/release.yml:53","Info:   0 out of  10 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   8 third-party GitHubAction dependencies pinned","Info:   0 out of   2 containerImage dependencies pinned","Info:   1 out of   7 pipCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact v1.11.4 not signed: https://api.github.com/repos/emojirades/emojirades/releases/207614425","Warn: release artifact v1.11.2 not signed: https://api.github.com/repos/emojirades/emojirades/releases/207581702","Warn: release artifact v1.11.1 not signed: https://api.github.com/repos/emojirades/emojirades/releases/207415855","Warn: release artifact v1.10.0 not signed: https://api.github.com/repos/emojirades/emojirades/releases/99730979","Warn: release artifact v1.9.0 not signed: https://api.github.com/repos/emojirades/emojirades/releases/84897386","Warn: release artifact v1.11.4 does not have provenance: https://api.github.com/repos/emojirades/emojirades/releases/207614425","Warn: release artifact v1.11.2 does not have provenance: https://api.github.com/repos/emojirades/emojirades/releases/207581702","Warn: release artifact v1.11.1 does not have provenance: https://api.github.com/repos/emojirades/emojirades/releases/207415855","Warn: release artifact v1.10.0 does not have provenance: https://api.github.com/repos/emojirades/emojirades/releases/99730979","Warn: release artifact v1.9.0 does not have provenance: https://api.github.com/repos/emojirades/emojirades/releases/84897386"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 23 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-18T14:17:10.757Z","repository_id":40425374,"created_at":"2025-08-18T14:17:10.757Z","updated_at":"2025-08-18T14:17:10.757Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29638782,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-19T22:32:43.237Z","status":"online","status_checked_at":"2026-02-20T02:00:07.535Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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","emojirades","emojirades-game","python","slack"],"created_at":"2026-01-18T09:19:50.741Z","updated_at":"2026-02-20T02:08:40.346Z","avatar_url":"https://github.com/emojirades.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Emojirades\nSlack bot that understands the emojirades game and handles score keeping.\n\n![CI Status](https://github.com/emojirades/emojirades/actions/workflows/ci.yml/badge.svg) ![PyPI version](https://badge.fury.io/py/emojirades.svg)\n\n# Developing\n## Install the dependencies\n```bash\npip3 install --upgrade pip wheel\n```\n\n## Install the module \u0026 dependencies\n```bash\npip3 install -e .[dev]\n```\n\n## Run the tests\n```bash\n# Linter\npylint emojirades\n\n# Formatter\nblack --check .\n\n# Tests\n./scripts/run_tests.sh\n```\n\n## Creating new DB revisions\nIf you make changes to `emojirades/persistence/models` you'll need to generate new revisions. This tracks the changes and applies them to the DB at each bots startup\n```\ncd emojirades/persistence/models\nalembic revision --autogenerate --message \"\u003cuseful insightful few words\u003e\"\n```\n\n# Running\n## Set Environment Variables\nIf you're using an auth file from AWS S3 you'll need to set the appropriate `AWS_` environment variables!\n\n## Separate Database\nUsing a database like PostgreSQL, you'll need to have created a database with a username and password before starting this.\n\nIf you've just created a fresh DB, you'll need to load the initial database:\n```\nemojirades -vv init --db-uri \"sqlite:///emojirades.db\"\n```\n\nAfter initialising the DB you can load in any optional pre-existing state.\n\nThe json files must be a list of objects, with each objects `key: value` representing a column in the associated model\n\nIf you are coming from the old style of state.json and scores.json you can run the following to produce json files that can be used in the above populate command\n\n```\n./bin/old_to_new_persistence.py --workspace-id TABC123 --state-file state.json --score-file scores.json\n```\n\nThis will produce `state.json.processed`, `scores.json.processed_scores` and `scores.json.processed_score_history`\n\nThey can be populated by running:\n```\nemojirades -vv populate --db-uri \"sqlite:///emojirades.db\" --table gamestate --data-file state.json.processed\nemojirades -vv populate --db-uri \"sqlite:///emojirades.db\" --table scoreboard --data-file scores.json.processed_scores\nemojirades -vv populate --db-uri \"sqlite:///emojirades.db\" --table scoreboard_history --data-file scores.json.processed_score_history\n```\n\n## Run the daemon for a single workspace\nThis command uses locally stored files to keep the game state:\n\n`emojirades single --db-uri sqlite:///emojirades.db --auth-uri auth.json`\n\nThis command uses a separate PostgreSQL DB and an auth file from AWS S3:\n\n`emojirades single --db-uri postgresql://user:pass@hostname/database --auth-uri s3://bucket/auth.json`\n\n## Run the daemon for multiple workspaces\nHere we provide a local folder of workspaces and an optional set of workspace ids (will load all in folder by default):\n\n`emojirades mulitple --workspaces-dir path/to/workspaces [--workspace-id A1B2C3D4E]`\n\nHere we provide an S3 path of workspaces and an optional set of workspace ids (will load all in folder by default):\n\n`emojirades multiple --workspaces-dir s3://bucket/path/to/workspaces [--workspace-id A1B2C3D4E]`\n\nHere we provide an S3 path of workspaces and an AWS SQS queue to listen to for new workspaces:\n\n`emojirades multiple --workspaces-dir s3://bucket/path/to/workspaces --onboarding-queue workspace-onboarding-queue`\n\nHere we provide an S3 path of workspaces and override the db_uri:\n\n`emojirades multiple --workspaces-dir s3://bucket/path/to/workspaces --db-uri sqlite:///emojirades.db`\n\nThe workspaces directory must be in the following format (local or s3):\n```\n./workspaces\n\n./workspaces/shards\n./workspaces/shards/0\n./workspaces/shards/0/A1B2C3D4E.json\n./workspaces/shards/0/Z9Y8X7W6V.json\n\n./workspaces/directory\n./workspaces/directory/A1B2C3D4E\n./workspaces/directory/A1B2C3D4E/auth.json\n./workspaces/directory/Z9Y8X7W6V\n./workspaces/directory/Z9Y8X7W6V/auth.json\n```\n\nEach instance of the bot will listen to a specific shard (specified as the --workspaces-dir).\n\nThe contents of the shard config (eg. `./workspaces/shards/0/A1B2C3D4E.json`) will be a file similar to:\n```\n{\n  \"workspace_id\": \"A1B2C3D4E\",\n  \"db_uri\": \"sqlite:////data/emojirades.db\",  # Optional, needed if you do not specify one with the bot itself\n  \"auth_uri\": \"s3://bucket/workspaces/directory/A1B2C3D4E/auth.json\",\n}\n```\n\nThe concept above with the two different directories is shards to allow for the bot to scale out horizontally. As the bot(s) get busier, the operator can increase the shard count (number of bot instances) and new onboarded workspaces are allocated to the next available shard with capacity.\n\nThe emojirades bot will take care of running multiple games across different channels in a single workspace. This is a limitation in the design currently where you need a bot-per-workspace.\n\n## Service configuration\n```\ncp emojirades.service /etc/systemd/system/\nsudo chmod 0664 /etc/systemd/system/emojirades.service\n\n# Edit the /etc/systemd/system/emojirades.service file and update the user and group\n\ncp emojirades.config /etc/emojirades\nsudo chmod 0400 /etc/emojirades\n\n# Edit the /etc/emojirades config file with your configuration for the bot\n\nsudo systemctl daemon-reload\nsudo systemctl enable emojirades\nsudo systemctl start emojirades\n\n```\n# Release process\n1. Checkout master branch\n2. Update `emojirades/__init__.py` with the new version (vX.Y.Z)\n3. Commit\n4. Tag the commit with vX.Y.Z\n5. `git push; git push --tags` together\n4. Github Actions will trigger the Release Job when a tagged commit to master is detected\n    1. Changelog will be generated and a Github Release as well with the changelog\n    2. New python wheel will be built and published to PyPI and attached to the Release\n    3. New container image will be built and published to Github Container Registry\n\n## Building the Container Image\n```\ndocker build --pull --no-cache -t ghcr.io/emojirades/emojirades:X.Y.Z -t ghcr.io/emojirades/emojirades:latest .\n```\n\n## Running the Container\nIn this example we run the game with S3 hosted configuration for a single workspace.\n\n```\ndocker run -d \\\n  --name emojirades \\\n  --restart=always \\\n  -v \"/path/to/your/.aws/:/root/.aws/:ro\" \\\n  -v \"emojirades-data:/data\" \\\n  -e \"AWS_PROFILE=emojirades\" \\\n  ghcr.io/emojirades/emojirades:X.Y.X \\\n    --db-uri sqlite:////data/emojirades.db \\\n    --auth-uri s3://bucket/path/to/auth.json \\\n    -vv\n```\n\n## Migrating from SQLite to Postgres\nThis assumes you have a local copy of your sqlite DB file and already setup and can access your postgres DB.\n\n```bash\n# Sourced venv/etc\n\n# Init the DB to setup the table structure\n./bin/emojirades init --db-uri 'postgresql+psycopg2://user:password@host:port/dbname'\n\n# Run the migration script\n./bin/sqlite_to_postgres.py \\\n    --source-db-uri 'sqlite+pysqlite:///relative/path/to/emojirades.db' \\\n    --target-db-uri 'postgresql+psycopg2://user:password@host:port/dbname'\n\n# Update the sequences by logging into postgres and resetting them to +1\nemojirades=# select max(event_id) from gamestate_history;\n max\n------\n 3086\n(1 row)\n\nemojirades=# ALTER SEQUENCE gamestate_history_event_id_seq RESTART WITH 3087;\nALTER SEQUENCE\n\nemojirades=# select max(event_id) from scoreboard_history;\n max\n------\n 1622\n(1 row)\n\nemojirades=# ALTER SEQUENCE scoreboard_history_event_id_seq RESTART WITH 1623;\nALTER SEQUENCE\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Femojirades%2Femojirades","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Femojirades%2Femojirades","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Femojirades%2Femojirades/lists"}