Skip to main content

Single interface for several game mod portals

Project description

ModMux

PyPI Python License CI

Unified async client for multiple game mod platforms. ModMux normalises provider responses into shared Pydantic models and ships a small CLI for quick lookups.

Features

  • Async HTTP client with rate limiting and retry handling
  • Normalised Mod metadata model across providers
  • Bulk get_mods(...) support with native batching where available
  • Pluggable provider registry
  • URL parsing helpers for provider links
  • CLI for fetching one or more mods and printing JSON

Supported providers

  • Modrinth
  • CurseForge
  • Nexus Mods
  • Mod.io
  • Steam Workshop
  • Factorio Mod Portal (Wube)

Requirements

  • Python 3.13+
  • Dependencies: pydantic, httpx, aiolimiter

Install

python -m pip install modmux

Credentials and environment variables

  • --token accepts API tokens/keys.
  • --user supplies a user id for providers that need user-scoped base URLs (mod.io).
  • Environment variables:
    • MODMUX_TOKEN (fallback for all providers)
    • MODMUX_<PROVIDER>_TOKEN (provider-specific, e.g. MODMUX_MODRINTH_TOKEN)
    • MODMUX_<PROVIDER>_USER (provider-specific user id, e.g. MODMUX_MODIO_USER)

Library usage

Two supported patterns are available: an async context manager or a manually closed client.

import asyncio

from modmux import ModID, ModrinthCreds, Muxer, Provider

mod_id = ModID(provider=Provider.MODRINTH, id="fabric-api")


async def run() -> None:
    async with Muxer(creds=[ModrinthCreds(api_key="api-key")]) as mux:
        mod = await mux.get_mod(Provider.MODRINTH, mod_id)
    print(mod.name)


asyncio.run(run())

Use the same context manager pattern as above; you can supply multiple provider credentials in one go:

from modmux import ModioCreds, Muxer, NexusCreds, SteamCreds

mux = Muxer(
    creds=[
        ModioCreds(api_key="api-key", user_id="user-id"),
        NexusCreds(token="nexus-token"),
        SteamCreds(api_key="steam-key"),
    ]
)
import asyncio

from modmux import ModID, Muxer, Provider

mod_id = ModID(provider=Provider.MODRINTH, id="fabric-api")


async def run() -> None:
    mux = Muxer()
    try:
        mod = await mux.get_mod(Provider.MODRINTH, mod_id)
    finally:
        await mux.aclose()
    print(mod.name)


asyncio.run(run())

The modmux_client(...) helper remains available as a convenience wrapper around Muxer for existing code.

You can also pass raw credential dicts when you do not want to import the credential models directly:

from modmux import ModID, Muxer, Provider

mod_id = ModID(provider=Provider.MODRINTH, id="fabric-api")

async with Muxer(creds={Provider.MODRINTH: {"token": "token"}}) as mux:
    mod = await mux.get_mod(Provider.MODRINTH, mod_id)

You can also fetch multiple mods in one call:

from modmux import ModID, Muxer, Provider

mod_ids = [
    ModID(provider=Provider.STEAM, id="123"),
    ModID(provider=Provider.STEAM, id="456"),
]

async with Muxer() as mux:
    mods = await mux.get_mods(Provider.STEAM, mod_ids)

URL parsing

Parse provider URLs into ModID instances, or fetch directly from a URL.

import asyncio

from modmux import Muxer, parse_url


async def run_mod_id() -> None:
    async with Muxer() as mux:
        mod = await mux.get_mod_from_url("https://modrinth.com/mod/fabric-api")
    print(mod.name)

async def run_from_url() -> None:
    mod_id = parse_url("https://modrinth.com/mod/fabric-api")
    if mod_id:
        async with Muxer() as mux:
            mod = await mux.get_mod(mod_id.provider, mod_id)
        print(mod.name)

asyncio.run(run())

Some providers require extra context (game ids or credentials); use get_mod_from_url(..., game="...") when the URL cannot supply it.

CLI usage

The CLI expects a provider name and one or more provider-specific mod ids. Provider names are case-insensitive.

modmux MODRINTH fabric-api --pretty
modmux CURSEFORGE 238222 --pretty
modmux STEAM 123 456 --pretty
modmux NEXUSMODS 12345 --game transportfever2
modmux MODIO some-mod --game 4321 --user 12345 --token <api-key>
modmux --from-urls urls.txt --pretty

Or without installing a script:

python -m modmux MODRINTH fabric-api --pretty

Output is a JSON serialisation of a single Mod when one id is provided, or a JSON array of Mod objects when multiple ids are provided.

When using --from-urls, provide one mod URL per line. Blank lines and lines starting with # are ignored. URLs are grouped by provider internally so the CLI can reuse native bulk lookups where available.

Provider notes

  • CurseForge: slug lookups require ModID.game (numeric game id or game slug from a CurseForge URL).
  • Nexus Mods: requires ModID.game (game domain, e.g. skyrim).
  • mod.io: requires ModID.game plus a user id (use --user or MODMUX_MODIO_USER).
  • Steam: uses a Workshop published file id; ModID.game is optional.
  • Wube: uses the Factorio mod name slug.
  • Native bulk lookup is currently implemented for Modrinth, CurseForge, Steam Workshop, and mod.io.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

modmux-0.4.0.tar.gz (29.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

modmux-0.4.0-py3-none-any.whl (44.0 kB view details)

Uploaded Python 3

File details

Details for the file modmux-0.4.0.tar.gz.

File metadata

  • Download URL: modmux-0.4.0.tar.gz
  • Upload date:
  • Size: 29.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for modmux-0.4.0.tar.gz
Algorithm Hash digest
SHA256 5e38b677d862731c3fb9559b76f748fcadc7efed14703bf55768ab3fb6a8284a
MD5 e790cb25719c7a7dc48785d78d4ae27c
BLAKE2b-256 26135eaab09576acc6cc7a10fec45106169909595da7019901ad800b0d48cdd5

See more details on using hashes here.

File details

Details for the file modmux-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: modmux-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 44.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for modmux-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 21aea45bb96b32dbd8e91e219ae9186fc866808150a0b1ca0a7fe6c392c5a619
MD5 e94cf1737eae01a7deddba72268e7831
BLAKE2b-256 f556eac67febaa884dcb700d02c7eaa9c0855d8a226c4e2c8d9562b0188ecced

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page