Initial bridge: Discord <-> Fluxer channel relay via webhooks
- discord.py + fluxer.py bots run side-by-side in one asyncio process - messages relay through per-channel incoming webhooks with the original author's name and avatar (suffixed '(Discord)' / '(Fluxer)') - loop protection: bot-authored and webhook-authored messages are ignored - attachments re-uploaded natively both directions (8 MB cap) - emoji mirroring: on-demand upload into the receiving guild with LRU eviction of bridge-created emojis only; pre-existing emojis untouched; to-Discord direction opt-in (50-slot default guild cap)
This commit is contained in:
1 parent
09ce07d403
commit
f3154396fa
9 files changed
+1405
-2
No files matched your search
+154
@@ -0,0 +1,154 @@
|
||||
# itako — INSTALL
|
||||
|
||||
Bridge one Discord channel and one Fluxer channel so messages cross between
|
||||
them, shown as webhook posts with the original author's name and avatar.
|
||||
|
||||
## Requirements
|
||||
|
||||
- **Python 3.11+**
|
||||
- **[uv](https://docs.astral.sh/uv/)** (package manager) — `pip install uv` or
|
||||
the [standalone installer](https://docs.astral.sh/uv/getting-started/installation/)
|
||||
- A machine that can reach `discord.com`, `fluxer.app`, and
|
||||
`gateway.fluxer.app` over HTTPS/WSS.
|
||||
|
||||
## 1. Discord bot
|
||||
|
||||
1. Go to the [Discord Developer Portal](https://discord.com/developers/applications)
|
||||
→ **New Application**.
|
||||
2. **Bot** tab → *Reset Token* → copy the token (you'll paste it into `.env`).
|
||||
3. **Bot** tab → *Privileged Gateway Intents* → enable:
|
||||
- **MESSAGE CONTENT INTENT** (required — without it the bot can't read text)
|
||||
- **SERVER MEMBERS INTENT** (not required) · **PRESENCE INTENT** (not required)
|
||||
4. **OAuth2 → URL Generator**: check `bot`, then permissions:
|
||||
- Manage Webhooks
|
||||
- Send Messages
|
||||
- View Channels / View Server Insights (read access to the relay channel)
|
||||
5. Open the generated URL, invite the bot to your server.
|
||||
|
||||
> The bridge creates one webhook named `itako-bridge` in the relay channel on
|
||||
> first run and reuses it afterwards. You can also create it manually with
|
||||
> that exact name if you prefer.
|
||||
|
||||
## 2. Fluxer bot
|
||||
|
||||
Fluxer's API is Discord-compatible; bots are created similarly:
|
||||
|
||||
1. In Fluxer: **Settings → Applications** (or the developer portal) → create a
|
||||
**bot application**. Copy the **bot token** and note the **client secret**
|
||||
(only needed for OAuth flows — this bridge doesn't use it).
|
||||
2. Invite the bot to your Fluxer guild with:
|
||||
- Manage Webhooks
|
||||
- Send Messages
|
||||
- Read Messages
|
||||
|
||||
## 3. Get the channel & guild IDs
|
||||
|
||||
Enable Developer Mode to right-click → **Copy ID**:
|
||||
|
||||
| Platform | How |
|
||||
|---|---|
|
||||
| Discord | User Settings → Advanced → Developer Mode; right-click guild/channel → Copy ID |
|
||||
| Fluxer | Same pattern as Discord (it's wire-compatible) |
|
||||
|
||||
You need: **Discord guild id**, **Discord channel id**, **Fluxer guild id**,
|
||||
**Fluxer channel id**.
|
||||
|
||||
## 4. Configure
|
||||
|
||||
```bash
|
||||
cd Code/itako
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
Edit `.env`:
|
||||
|
||||
```ini
|
||||
DISCORD_TOKEN = "your-discord-bot-token"
|
||||
FLUXER_TOKEN = "your-fluxer-bot-token"
|
||||
|
||||
DISCORD_CHANNEL_ID = "1234567890123456789"
|
||||
FLUXER_CHANNEL_ID = "9876543210987654321"
|
||||
|
||||
DISCORD_GUILD_ID = "1111111111111111111"
|
||||
FLUXER_GUILD_ID = "2222222222222222222"
|
||||
```
|
||||
|
||||
Guild IDs are used for emoji-name lookups (so matching custom emojis render
|
||||
natively instead of degrading to `:name:` text). Quotes are optional;
|
||||
`python-dotenv` handles both styles.
|
||||
|
||||
Optional keys:
|
||||
|
||||
```ini
|
||||
BRIDGE_WEBHOOK_NAME = "itako-bridge" # webhook name created/reused per channel
|
||||
|
||||
# Emoji mirroring: upload unknown emojis into the receiving guild on first
|
||||
# use, evicting the least-recently-used *bridge-created* emoji when the cap
|
||||
# is hit. Pre-existing emojis are never touched or counted.
|
||||
EMOJI_MIRROR_TO_FLUXER = true # mirror Discord emojis into Fluxer (default)
|
||||
EMOJI_MIRROR_CAP_FLUXER = 150 # Fluxer's hard cap is 500; stay well under
|
||||
EMOJI_MIRROR_TO_DISCORD = false # off by default — normal Discord guilds have
|
||||
# only 50 emoji slots; set true + raise cap if
|
||||
# your guild has more slots to spare
|
||||
EMOJI_MIRROR_CAP_DISCORD = 30
|
||||
```
|
||||
|
||||
## 5. Install dependencies
|
||||
|
||||
```bash
|
||||
uv sync
|
||||
```
|
||||
|
||||
This pulls in `discord.py`, `fluxer-py` (from GitHub), `python-dotenv`,
|
||||
and `aiohttp`.
|
||||
|
||||
## 6. Run
|
||||
|
||||
```bash
|
||||
uv run python -m itako.bridge
|
||||
```
|
||||
|
||||
Expected startup log:
|
||||
|
||||
```
|
||||
itako INFO Fluxer connected as <botname>
|
||||
itako INFO Reusing Fluxer webhook ...
|
||||
itako INFO Reusing Discord webhook ...
|
||||
itako INFO Loaded N Fluxer emojis
|
||||
itako INFO Discord connected as <botname>#0000
|
||||
itako INFO Loaded N Discord emojis
|
||||
```
|
||||
|
||||
Send a message in either channel — it should appear in the other within a
|
||||
second, posted by the `itako-bridge` webhook with the author's username
|
||||
(`name (Discord)` / `name (Fluxer)`) and avatar.
|
||||
|
||||
### Run at startup (optional)
|
||||
|
||||
For an always-on bridge, wrap the command in a service, e.g. with
|
||||
[NSSM](https://nssm.cc/) on Windows:
|
||||
|
||||
```
|
||||
nssm install itako "C:\path\to\uv.exe" run python -m itako.bridge
|
||||
nssm set itako AppDirectory C:\Users\<you>\Code\itako
|
||||
nssm start itako
|
||||
```
|
||||
|
||||
(Or see TODO.md for planned first-class service support.)
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Symptom | Fix |
|
||||
|---|---|
|
||||
| Discord logs `session has been invalidated` repeatedly | Message Content intent not enabled in the Developer Portal |
|
||||
| Messages relay but show no avatar | Author has default avatar; bridge substitutes platform default |
|
||||
| Emojis show as `:name:` | That emoji doesn't exist on the receiving side; add it there or ignore |
|
||||
| `AttributeError: 'NoneType' object has no attribute ... fluxer` | Fluxer bot token wrong, or bot not invited to the guild/channel |
|
||||
| Nothing relays at all | Check both channel IDs point at channels the respective bot can read |
|
||||
|
||||
## Behavior notes
|
||||
|
||||
- Bot-authored and webhook-authored messages are ignored (loop prevention).
|
||||
- Attachments up to **8 MB** are re-uploaded natively so images embed inline.
|
||||
- Custom emojis are **never uploaded/mirrored** — only rewritten when the same
|
||||
emoji name exists on the receiving platform (no slot usage on either side).
|
||||
Reference in new issue
Block a user