Skip to main content

Mhanndalorian_Bot

Mhanndalorian_Bot is a Python library for interacting with the SWGOH Mhanndalorian Bot authenticated API and Player Registry endpoints.

See https://mhanndalorianbot.work/apidocs.html for the full API reference.

Installation

Use the Python package manager pip to install Mhanndalorian_Bot.

   pip install mhanndalorian-bot

Usage

Before accessing the Mhanndalorian Bot APIs you must first register for an apikey. Instructions for generating an apikey can be found in the API reference.

Basic Usage

Authenticated API Endpoint Interaction

from mhanndalorian_bot import API, EndPoint

mbot = API(api_key=<YOUR APIKEY>, allycode=<YOUR ALLYCODE>)

resp = mbot.fetch_data(endpoint=EndPoint.INVENTORY)

Player Registry Interaction

from mhanndalorian_bot import Registry

mbot = Registry(api_key=<YOUR APIKEY>, allycode=<YOUR ALLYCODE>, discord_id=<YOUR DISCORD USER ID>)

resp = mbot.fetch_player(allycode=<PLAYER ALLYCODE>)

Credentials from environment variables

Constructor arguments may be omitted when the MHANN_API_KEY, MHANN_ALLYCODE, and (optionally) MHANN_DISCORD_ID environment variables are set:

from mhanndalorian_bot import API

mbot = API()  # reads MHANN_API_KEY and MHANN_ALLYCODE

Authenticated vs non-authenticated endpoints

The API distinguishes two endpoint groups. Authenticated endpoints log in as the registered player and will break that player's active in-game session: tw, twlogs, twleaderboard, tb, tblogs, tbleaderboardhistory, activeraid, gac, inventory, leaderboard, squadpresets, conquest, and events. Non-authenticated endpoints (player, playerarena, guild, guildleaderboard, database) do not touch the game session. Programmatically, check EndPoint.TW.is_authenticated.

Calling one emits a SessionBreakWarning — once per endpoint per process, not once per call, so a bot polling on a timer is warned rather than spammed. Silence it the usual way:

import warnings
from mhanndalorian_bot import SessionBreakWarning

warnings.filterwarnings("ignore", category=SessionBreakWarning)

Discord ID is required for non-authenticated endpoints

The API rejects the five Non-authenticated endpoints — player, playerarena, guild, guildleaderboard, database — with a 400 when the x-discord-id header is absent. The library checks locally and raises ValidationError rather than spending a round-trip on a request the server will refuse:

mbot = API(api_key=..., allycode=...)          # no discord_id
mbot.fetch_player(allycode=...)                # ValidationError: 'player' requires a Discord ID

mbot = API(api_key=..., allycode=..., discord_id=...)
mbot.fetch_player(allycode=...)                # fine

Set it via the constructor, the MHANN_DISCORD_ID environment variable, or set_discord_id(). Authenticated endpoints are unaffected, and so is the registry's /comlink path, which carries its Discord ID in the payload instead. Check programmatically with EndPoint.PLAYER.requires_discord_id.

Error handling

Everything the library raises subclasses MBotError, which subclasses RuntimeError. Below it the hierarchy splits in two, and the split matters when you write handlers:

RuntimeError
└── MBotError                    every error the library raises
    ├── ValidationError          your input was rejected locally, before any request was sent
    └── APIResponseError         non-200 response  (.status_code, .endpoint, .response_text)
        ├── BadRequestError      400
        ├── AuthenticationError  401 - bad API key or HMAC signature
        └── AuthorizationError   403 - not authorised for this account or endpoint

Only APIResponseError and its subclasses carry status_code / endpoint / response_text. A ValidationError describes a request that never left the client, so it has no response to report. Catch APIResponseError — not MBotError — when you intend to read those attributes:

from mhanndalorian_bot import API, APIResponseError, AuthenticationError, ValidationError

mbot = API(api_key=<YOUR APIKEY>, allycode=<YOUR ALLYCODE>, discord_id=<YOUR DISCORD USER ID>)

try:
    data = mbot.fetch_player(allycode=<PLAYER ALLYCODE>)
except ValidationError as exc:      # bad allycode, count out of range, defId/type mismatch...
    print(f"bad input: {exc}")
except AuthenticationError:         # HTTP 401
    ...
except APIResponseError as exc:     # any other non-200 (400, 403, 5xx, ...)
    print(exc.status_code, exc.endpoint, exc.response_text)

except MBotError: is still the right catch-all when you only need "something went wrong" and won't touch response attributes.

Upgrading from 0.10.x

ValidationError does not subclass ValueError or TypeError. Handlers that previously caught those around library calls silently stop catching:

# before 0.11.0
try:
    mbot.fetch_player("123-456-789")
except ValueError:
    ...

# 0.11.0 onwards
try:
    mbot.fetch_player("123-456-789")
except ValidationError:
    ...

except RuntimeError: and except MBotError: keep working throughout. A TypeError raised by Python itself against a method signature — an unknown keyword, a missing positional — is a programming error rather than bad input, and is deliberately still a plain TypeError.

Note also that fetch_player("123-456-789") now sends 123456789: per-call allycodes are cleansed the same way constructor allycodes always were, and one that isn't 9 digits raises instead of reaching the server.

fetch_player and fetch_guild no longer strip the response envelope. They were the only two helpers that ever did; every other helper always returned it. The envelope differs per endpoint — /conquest returns three sibling keys, /tblogs two — so there is no uniform thing to unwrap to, and returning it whole is the only rule definable across all 18 endpoints.

# before 0.11.0
name = mbot.fetch_player(allycode=...)["name"]
guild = mbot.fetch_guild(guild_id=...)["profile"]

# 0.11.0 onwards
name = mbot.fetch_player(allycode=...)["events"]["name"]
guild = mbot.fetch_guild(guild_id=...)["events"]["guild"]["profile"]

Registry.verify_player(primary=...) defaults to None, not False. With None the key is omitted from the payload entirely, letting the registry apply its documented behaviour: a user with no other registered accounts gets primary: yes. The old False default silently opted first-time users out of being primary. Pass True or False to state it explicitly.

Discord IDs of 17–20 digits are now accepted (previously exactly 18). This only widens what is allowed, so it breaks nobody — but it is worth knowing that every Discord account created since ~July 2022 has a 19-digit ID and was rejected outright before this release, which made Registry unusable for those users.

Guild leaderboards and player arena

Three leaderboard types require a def_id, and each takes it from its own enum — the API constrains the pairing, not just the value, so GuildRaidDefId is only valid with GUILD_RAID_HIGH_WATERMARK:

LeaderboardType def_id
UNSPECIFIED, GUILD_RAID_ALL_COMP_PTS, GUILD_GALACTIC_POWER none — passing one is rejected
GUILD_TERRITORY_BATTLE_STARS TerritoryBattleDefId
GUILD_TERRITORY_WAR_OPPONENT_GALACTIC_POWER TerritoryWarDefId
GUILD_RAID_HIGH_WATERMARK GuildRaidDefId
from mhanndalorian_bot import API, GuildRaidDefId, LeaderboardType

# guildleaderboard and playerarena are non-authenticated endpoints, so a Discord ID is required.
mbot = API(api_key=<YOUR APIKEY>, allycode=<YOUR ALLYCODE>, discord_id=<YOUR DISCORD USER ID>)

top_gp = mbot.fetch_guild_leaderboard(LeaderboardType.GUILD_GALACTIC_POWER, count=100)
raid = mbot.fetch_guild_leaderboard(LeaderboardType.GUILD_RAID_HIGH_WATERMARK,
                                    def_id=GuildRaidDefId.RANCOR_DIFF01)

# raw strings work too, exactly like EndPoint
raid = mbot.fetch_guild_leaderboard(LeaderboardType.GUILD_RAID_HIGH_WATERMARK,
                                    def_id="GUILD:RAIDS:NORMAL_DIFF:RANCOR:DIFF01")

# playerarena is also a lightweight allycode <-> playerId translation
profile = mbot.fetch_player_arena(player_id=<PLAYER ID>)

count must be 1–200. A missing, mismatched, or unexpected def_id raises ValidationError locally rather than sending a request the API would reject with a 400.

fetch_player and fetch_player_arena accept either allycode or player_id (mutually exclusive).

Applications approved to act on behalf of other users can pass user_discord_id=<DISCORD ID> to any fetch helper; this forces HMAC signing as the API requires. One caveat worth knowing: the API spec declares userDiscordId for the authenticated endpoints and for player / playerarena, but not for guild / guildleaderboard. The library sends it wherever you pass it; whether the server honours it on those two endpoints is unverified.

The enums flag

Every fetch helper accepts enums (default False), which selects how the API renders enum fields in the response:

  • enums=False → integer values
  • enums=True → string names
mbot.fetch_inventory()              # enum fields come back as integers
mbot.fetch_inventory(enums=True)    # ...as string names

Timeouts and retries

mbot = API(api_key=<YOUR APIKEY>, allycode=<YOUR ALLYCODE>, timeout=30.0, retries=2)

timeout (seconds, default 75) applies to every request; retries (default 0) retries failed connection attempts only — failed responses are never retried.

Resource cleanup

API and Registry hold open HTTP connections. For long-running services use the (async-)context manager so the underlying client is closed on exit:

from mhanndalorian_bot import API

with API(api_key=<YOUR APIKEY>, allycode=<YOUR ALLYCODE>) as mbot:
    data = mbot.fetch_inventory()

# async
import asyncio
from mhanndalorian_bot import API

async def main():
    async with API(api_key=<YOUR APIKEY>, allycode=<YOUR ALLYCODE>) as mbot:
        data = await mbot.fetch_inventory_async()

asyncio.run(main())

close() / aclose() are also available for explicit cleanup outside a with block.

TLS verification

TLS certificate verification uses the system trust store by default. Pass a CA bundle path via verify="/path/to/ca.pem" for custom roots, or verify=False to disable verification (NOT recommended — exposes API keys and signed requests to MITM).

Advanced Usage

mhanndalorian_bot includes async methods in both the API and Registry modules. These are provided to facilitate usage within Python scripts that may primarily make use of the asyncio (or equivalent) module, such as Discord bots. Since the Mhanndalorian web services/APIs deal with SWGOH player registration and data access, it is likely that the primary consumers of those services will be bots.

Authenticated API Endpoint Interaction

import asyncio
from mhanndalorian_bot import API, EndPoint, MBotError

async def main():
    mbot = API(api_key="super_secret_test_key", allycode="123456789")

    try:
        fetch_data_resp = await mbot.fetch_data_async(EndPoint.INVENTORY)
    except MBotError as exc:
        print(f"API error {exc.status_code} from {exc.endpoint}: {exc.response_text}")
        return

    if 'inventory' in fetch_data_resp:
        material: list = fetch_data_resp['inventory']['material']
        currency: list = fetch_data_resp['inventory']['currencyItem']
        equipment: list = fetch_data_resp['inventory']['equipment']
        unequipped_mods: list = fetch_data_resp['inventory']['unequippedMod']

if __name__ == '__main__':
    asyncio.run(main())

Player Registry Interaction

import asyncio
from mhanndalorian_bot import MBotError, Registry

async def main():
    reg = Registry(api_key=<YOUR API KEY>, allycode=<YOUR ALLYCODE>, discord_id=<YOUR DISCORD USER ID>)

    try:
        fetch_resp = await reg.fetch_player_async(allycode=<PLAYER ALLYCODE>)
    except MBotError as exc:
        print(f"Registry error {exc.status_code}: {exc.response_text}")
        return

    player_allycode = fetch_resp['allyCode']
    player_discord_id = fetch_resp['discordId']

if __name__ == '__main__':
    asyncio.run(main())

More information can be found on GitHub

Download files

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

Source Distribution

mhanndalorian_bot-0.11.0.tar.gz (96.7 kB view details)

Uploaded Source

Built Distribution

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

mhanndalorian_bot-0.11.0-py3-none-any.whl (31.2 kB view details)

Uploaded Python 3

File details

Details for the file mhanndalorian_bot-0.11.0.tar.gz.

File metadata

  • Download URL: mhanndalorian_bot-0.11.0.tar.gz
  • Upload date:
  • Size: 96.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for mhanndalorian_bot-0.11.0.tar.gz
Algorithm Hash digest
SHA256 fdf781558fb39e01ab4d977956b64c2a2324806461dcf7cbb6da9638008de94a
MD5 a586e7de52292a5717e8aaab4f616375
BLAKE2b-256 8c7727ed2c62785754feded9cbeeb4fdc313fbc8970564f0bf5e8f88543f3423

See more details on using hashes here.

Provenance

The following attestation bundles were made for mhanndalorian_bot-0.11.0.tar.gz:

Publisher: release.yml on MarTrepodi/mhanndalorian-bot-api

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file mhanndalorian_bot-0.11.0-py3-none-any.whl.

File metadata

File hashes

Hashes for mhanndalorian_bot-0.11.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0c8e78b6a9c48fa657ca7efb0dc92457fe9e2fc2c57115414c75cad7a711f05d
MD5 6e890fa45b23e307414d130baf42b2b2
BLAKE2b-256 0f31edbfc13e9800d282b7ac29b01c7a00c60b4ef9a68cbbd91ad360bbcac5b8

See more details on using hashes here.

Provenance

The following attestation bundles were made for mhanndalorian_bot-0.11.0-py3-none-any.whl:

Publisher: release.yml on MarTrepodi/mhanndalorian-bot-api

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.11.0 This release

2 files

0.10.0

2 files

0.9.0

2 files

0.8.1

2 files

0.8.0

2 files

0.7.0

2 files

0.6.0

2 files

0.5.2

2 files

0.5.1

2 files

0.5.0

2 files

0.4.0

2 files

0.3.0

2 files

0.2.0

2 files

0.1.3

2 files

0.1.1

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page