{"id":21214517,"url":"https://github.com/slice/black-hole","last_synced_at":"2025-07-10T10:30:25.992Z","repository":{"id":55896132,"uuid":"142212269","full_name":"slice/black-hole","owner":"slice","description":"XMPP ↔ Discord bridge in Python 3","archived":false,"fork":false,"pushed_at":"2022-01-24T05:45:30.000Z","size":82,"stargazers_count":9,"open_issues_count":1,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-04-14T06:09:08.663Z","etag":null,"topics":["bridge","discord","xmpp"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/slice.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-07-24T20:58:29.000Z","updated_at":"2023-11-18T20:19:34.000Z","dependencies_parsed_at":"2022-08-15T08:50:56.827Z","dependency_job_id":null,"html_url":"https://github.com/slice/black-hole","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slice%2Fblack-hole","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slice%2Fblack-hole/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slice%2Fblack-hole/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slice%2Fblack-hole/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/slice","download_url":"https://codeload.github.com/slice/black-hole/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225632206,"owners_count":17499744,"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":["bridge","discord","xmpp"],"created_at":"2024-11-20T21:28:16.716Z","updated_at":"2024-11-20T21:28:17.325Z","avatar_url":"https://github.com/slice.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# black-hole\n\nblack-hole is a configurable XMPP ↔ Discord bridge written in Python 3.6.\n\nIt uses [Discord.py@rewrite] and [aioxmpp].\n\n[discord.py@rewrite]: http://discordpy.readthedocs.io/en/rewrite/index.html\n[aioxmpp]: https://docs.zombofant.net/aioxmpp/devel/index.html\n\n## Requirements\n\n- Python 3.6+ (Tested on Python 3.7)\n\n## Configuring\n\nHere is a sample `config.yaml`:\n\n```yaml\n# XMPP credentials (JID and password).\nxmpp:\n  jid: 'bot@xmpp.server'\n  password: 'ramen'\n\n# black-hole supports multiple \"rooms\".\n#\n# The concept of a \"room\" in black-hole combines both a MUC and a Discord\n# channel. They are linked together with a Discord bot, a Discord webhook,\n# and an XMPP client.\nrooms:\n  - jid: 'general@muc.xmpp.server' # The JID of the MUC.\n\n    # The MUC's password. Omit if password-less.\n    # password: 'spicy ramen'\n\n    # The nickname to use when joining the MUC.\n    nick: 'black hole'\n\n    # The webhook URL to post to. (MUC → Discord)\n    webhook: 'https://discordapp.com/api/webhooks/...'\n\n    # The Discord channel's ID. (Discord → MUC)\n    channel_id: 123456789012345678\n\n    # Log any message sent in the MUC to standard out.\n    log: false\n\n    # Log any message sent in the linked Discord channel to standard out.\n    discord_log: false\ndiscord:\n  # Discord bot token, used to receive messages.\n  token: 'NDU...'\n\n  # A list of Discord user IDs that will be able to manage the bot from\n  # Discord.\n  managers:\n    - 123\n    - 456\n\n  # A map of JIDs to Discord user IDs.\n  # Allows black-hole to specify the avatar URL of a JID's associated Discord\n  # account when posting to the webhook.\n  jid_map:\n    'user_a@xmpp.server': 123\n    'user_b@xmpp.server': 456\n\n  # The delay in seconds between webhook sends (for maintaining message order).\n  delay: 0.25\n\n  # The delay in seconds before a cached avatar is invalidated and refetched,\n  # in seconds. The default is 30 minutes.\n  avatar_cache: 1800\n```\n\n## Documentation\n\n### Message Transport\n\nWebhooks are used to transfer messages from the MUC to Discord. The Discord bot\nlistens for messages in the specified channel and transfers them to the MUC.\n\nWe use a webhook because it allows us to customize the \"author\" and avatar of\nthe posted message, which makes mirrored messages easier to read.\n\n#### To Discord\n\n##### Mentions\n\nAny message travelling from MUC to Discord are stripped of mentions.\n\nAny role or user mention (including @everyone and @here) are escaped/stripped\nand do not mention anyone. Channel mentions are not, but you must send them in\n\"raw\" format (like `\u003c#123\u003e`).\n\n##### Queueing\n\nTo preserve message order, MUC messages are pushed into a queue and a background\nconsumer POSTs to the webhook with a (configurable) delay between requests.\n\n#### To MUC\n\n##### Attachments\n\nAny attachment URLs are appended to the end of the message, separated by spaces.\n\n##### Embeds\n\nIn the case of bots, the number of embeds present in the message is appended to\nthe end of the message.\n\n##### Message Edits\n\nWhen a message is edited on Discord, the edited version will be resent to the\nMUC with an \"(edited)\" prefix. aioxmpp presumably has no [XEP-0308] support, so\nwe can't use it, and even if it did support it, it would still be quite clunky\ndue to the way the XEP works.\n\n[xep-0308]: https://xmpp.org/extensions/xep-0308.html\n\nAny edits made on the MUC are not reflected on Discord.\n\n### JID Map\n\nThe JID map allows the XMPP → Discord functionality to resolve the user's avatar\nto be displayed through the webhook. It can be managed manually through the\nconfig file or through the Discord bot.\n\n#### Discord Management\n\nUse these commands to manage the JID map from Discord:\n\n```\n# Map a JID to a Discord user. You can provide the user ID, mention, or a username.\n@bot jid set \u003cjid\u003e \u003cuser\u003e\n\n# Deletes a JID from the JID map.\n@bot jid del \u003cjid\u003e\n\n# Shows the entire JID map.\n@bot jid show\n```\n\nThe `set` and `del` commands automatically save changes.\n\n### Disabling bridging\n\nYou can quickly toggle bridging using the Discord bot:\n\n```\n# Toggle the current room from being bridged.\n@bot room toggle\n\n# Toggle room@xmpp.server from being bridged.\n@bot room toggle room@xmpp.server\n```\n\nThis state persists between restarts (saved in configuration file).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fslice%2Fblack-hole","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fslice%2Fblack-hole","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fslice%2Fblack-hole/lists"}