feat(melonx): new melonx commands

Introduced new commands to the MeloNX cog: mods, gamecrash, requirements, error, and 26 (iOS 26), each with their own handler and help embed. Updated the README and melonx.py select menu to reflect the new commands. These additions provide users with troubleshooting and informational commands for common MeloNX issues and topics.
This commit is contained in:
neoarz
2025-10-04 08:54:48 -04:00
parent 023ec85640
commit ad1e117e75
8 changed files with 330 additions and 1 deletions

View File

@@ -26,7 +26,7 @@
| moderation | `kick`, `ban`, `nick`, `purge`, `hackban`, `warnings`, `archive` | | moderation | `kick`, `ban`, `nick`, `purge`, `hackban`, `warnings`, `archive` |
| sidestore | `sidestore`, `refresh`, `code`, `crash`, `pairing`, `server`, `half`, `sparse`, `afc`, `udid` | | sidestore | `sidestore`, `refresh`, `code`, `crash`, `pairing`, `server`, `half`, `sparse`, `afc`, `udid` |
| idevice | `idevice`, `noapps`, `errorcode`, `developermode`, `mountddi` | | idevice | `idevice`, `noapps`, `errorcode`, `developermode`, `mountddi` |
| melonx | `melonx`, `transfer` | | melonx | `melonx`, `transfer`, `mods`, `gamecrash`, `requirements`, `error`, `26` |
| miscellaneous | `keanu`, `labubu`, `piracy`, `tryitandsee`, `rickroll`, `dontasktoask`, `support`| | miscellaneous | `keanu`, `labubu`, `piracy`, `tryitandsee`, `rickroll`, `dontasktoask`, `support`|
| utilities | `translate`, `codepreview`, `dictionary` | | utilities | `translate`, `codepreview`, `dictionary` |
| media | `download` | | media | `download` |

View File

@@ -5,6 +5,11 @@ from discord.ext.commands import Context
from .melonx import MelonxView from .melonx import MelonxView
from .transfer import transfer_command from .transfer import transfer_command
from .mods import mods_command
from .gamecrash import crash_command
from .requirements import requirements_command
from .error import error_command
from .ios26 import ios26_command
class Melonx(commands.GroupCog, name="melonx"): class Melonx(commands.GroupCog, name="melonx"):
def __init__(self, bot) -> None: def __init__(self, bot) -> None:
@@ -37,6 +42,26 @@ class Melonx(commands.GroupCog, name="melonx"):
async def melonx_group_transfer(self, context: Context): async def melonx_group_transfer(self, context: Context):
await self._invoke_hybrid(context, "transfer") await self._invoke_hybrid(context, "transfer")
@melonx_group.command(name="mods")
async def melonx_group_mods(self, context: Context):
await self._invoke_hybrid(context, "mods")
@melonx_group.command(name="gamecrash")
async def melonx_group_gamecrash(self, context: Context):
await self._invoke_hybrid(context, "gamecrash")
@melonx_group.command(name="requirements")
async def melonx_group_requirements(self, context: Context):
await self._invoke_hybrid(context, "requirements")
@melonx_group.command(name="error")
async def melonx_group_error(self, context: Context):
await self._invoke_hybrid(context, "error")
@melonx_group.command(name="26")
async def melonx_group_26(self, context: Context):
await self._invoke_hybrid(context, "26")
async def _invoke_hybrid(self, context: Context, name: str): async def _invoke_hybrid(self, context: Context, name: str):
command = self.bot.get_command(name) command = self.bot.get_command(name)
if command is not None: if command is not None:
@@ -44,6 +69,16 @@ class Melonx(commands.GroupCog, name="melonx"):
else: else:
await context.send(f"Unknown MeloNX command: {name}") await context.send(f"Unknown MeloNX command: {name}")
def _require_group_prefix(context: Context) -> bool:
if getattr(context, "interaction", None):
return True
group = getattr(getattr(context, "cog", None), "qualified_name", "").lower()
if not group:
return True
prefix = context.prefix or ""
content = context.message.content.strip().lower()
return content.startswith(f"{prefix}{group} ")
@app_commands.command( @app_commands.command(
name="help", name="help",
description="MeloNX troubleshooting help" description="MeloNX troubleshooting help"
@@ -58,6 +93,7 @@ class Melonx(commands.GroupCog, name="melonx"):
view = MelonxView(self.bot) view = MelonxView(self.bot)
await interaction.response.send_message(embed=embed, view=view, ephemeral=True) await interaction.response.send_message(embed=embed, view=view, ephemeral=True)
@commands.check(_require_group_prefix)
@commands.hybrid_command( @commands.hybrid_command(
name="transfer", name="transfer",
description="How to transfer save files from other emulators or platforms" description="How to transfer save files from other emulators or platforms"
@@ -65,9 +101,54 @@ class Melonx(commands.GroupCog, name="melonx"):
async def transfer(self, context): async def transfer(self, context):
return await transfer_command()(self, context) return await transfer_command()(self, context)
@commands.check(_require_group_prefix)
@commands.hybrid_command(
name="mods",
description="How to install mods within MeloNX (Limited Support)"
)
async def mods(self, context):
return await mods_command()(self, context)
@commands.check(_require_group_prefix)
@commands.hybrid_command(
name="gamecrash",
description="Why does my game crash?"
)
async def gamecrash(self, context):
return await crash_command()(self, context)
@commands.check(_require_group_prefix)
@commands.hybrid_command(
name="requirements",
description="What does MeloNX require?"
)
async def requirements(self, context):
return await requirements_command()(self, context)
@commands.check(_require_group_prefix)
@commands.hybrid_command(
name="error",
description="What does this error message mean?"
)
async def error(self, context):
return await error_command()(self, context)
@commands.check(_require_group_prefix)
@commands.hybrid_command(
name="26",
description="How can I run MeloNX on iOS 26?"
)
async def ios26(self, context):
return await ios26_command()(self, context)
async def setup(bot) -> None: async def setup(bot) -> None:
cog = Melonx(bot) cog = Melonx(bot)
await bot.add_cog(cog) await bot.add_cog(cog)
bot.logger.info("Loaded extension 'melonx.help'") bot.logger.info("Loaded extension 'melonx.help'")
bot.logger.info("Loaded extension 'melonx.transfer'") bot.logger.info("Loaded extension 'melonx.transfer'")
bot.logger.info("Loaded extension 'melonx.mods'")
bot.logger.info("Loaded extension 'melonx.gamecrash'")
bot.logger.info("Loaded extension 'melonx.requirements'")
bot.logger.info("Loaded extension 'melonx.error'")
bot.logger.info("Loaded extension 'melonx.26'")

41
cogs/melonx/error.py Normal file
View File

@@ -0,0 +1,41 @@
import discord
from discord import app_commands
from discord.ext import commands
from discord.ext.commands import Context
import time
def error_command():
@commands.hybrid_command(
name="error", description="What does this error message mean?"
)
async def error(self, context):
embed = discord.Embed(
color=0x963155,
description=(
'# What does this error message mean?\n\n---\n\n' +
'**1. "MeloNX Crashed! System.SystemException: Cannot allocate memory"**' +
'You likely don\'t have the increased memory limit entitlement enabled, are using an a12 chipset, and have 4GB or less of memory. You can see the status of the entitlement for MeloNX under the Settings tab.\n\n' +
'**2. "MeloNX Crashed! LibHac.Common.HorizonResultException: ResultLoaderInvalidNso (2009-0005)"**' +
'This is likely a bad game / update / or DLC dump. redump your files and try again.'
)
)
embed.set_author(name="MeloNX", icon_url="https://yes.nighty.works/raw/TLGaVa.png")
embed.set_footer(text=f'Last Edited by neoarz')
embed.timestamp = discord.utils.utcnow()
view = discord.ui.View()
view.add_item(discord.ui.Button(
label="Edit Command",
style=discord.ButtonStyle.secondary,
url="https://github.com/neoarz/Syntrel/blob/main/cogs/melonx/error.py",
emoji="<:githubicon:1417717356846776340>"
))
if context.interaction:
await context.interaction.response.send_message(embed=embed, view=view)
else:
await context.send(embed=embed, view=view)
return error

46
cogs/melonx/gamecrash.py Normal file
View File

@@ -0,0 +1,46 @@
import discord
from discord import app_commands
from discord.ext import commands
from discord.ext.commands import Context
import time
def crash_command():
@commands.hybrid_command(
name="gamecrash", description="Why does my game crash?"
)
async def crash(self, context):
embed = discord.Embed(
color=0x963155,
description=(
'# "Why does my game crash?"\n\n---\n\n' +
'**This can be caused by multiple reasons:**\n' +
'- Not enough available ram\n' +
'- You may have tried to update your firmware without updating your keys\n' +
'- Game file is corrupted/broken\n' +
'- Game requires a higher firmware+keys combination than you currently have\n' +
'- In rare cases some games also crash when not having the resolution set to 1x\n' +
'- The a12 chipset have a lot of issues at the moment\n' +
'- Shader cache isn\'t cleared after updating MeloNX\n' +
'- iOS 15 and 16 are known to have some compatibility issues'
)
)
embed.set_author(name="MeloNX", icon_url="https://yes.nighty.works/raw/TLGaVa.png")
embed.set_footer(text=f'Last Edited by neoarz')
embed.timestamp = discord.utils.utcnow()
view = discord.ui.View()
view.add_item(discord.ui.Button(
label="Edit Command",
style=discord.ButtonStyle.secondary,
url="https://github.com/neoarz/Syntrel/blob/main/cogs/melonx/crash.py",
emoji="<:githubicon:1417717356846776340>"
))
if context.interaction:
await context.interaction.response.send_message(embed=embed, view=view)
else:
await context.send(embed=embed, view=view)
return crash

47
cogs/melonx/ios26.py Normal file
View File

@@ -0,0 +1,47 @@
import discord
from discord import app_commands
from discord.ext import commands
from discord.ext.commands import Context
import time
def ios26_command():
@commands.hybrid_command(
name="26", description="How can I run MeloNX on iOS 26?"
)
async def ios26(self, context):
embed = discord.Embed(
color=0x963155,
description=(
'# "How can I run MeloNX on iOS 26?"\n\n---\n\n' +
'### StikDebug\n' +
'1. Make sure StikDebug is on the latest version.\n' +
'2. Turn on "Picture in Picture" in StikDebug\'s settings.\n\n' +
'### MeloNX\n' +
'Make sure you\'re on the latest public beta.\n' +
'#prerelease-betas\n\n' +
'## Disclaimer:\n\n' +
'If you\'re on iOS 18 or below, and emulation is essential to you:\n\n' +
'## <:error:1424007141768822824> DO NOT UPDATE <:error:1424007141768822824> \n\n' +
'iOS 26 has many issues related to emulation.'
)
)
embed.set_author(name="MeloNX", icon_url="https://yes.nighty.works/raw/TLGaVa.png")
embed.set_footer(text=f'Last Edited by neoarz')
embed.timestamp = discord.utils.utcnow()
view = discord.ui.View()
view.add_item(discord.ui.Button(
label="Edit Command",
style=discord.ButtonStyle.secondary,
url="https://github.com/neoarz/Syntrel/blob/main/cogs/melonx/ios26.py",
emoji="<:githubicon:1417717356846776340>"
))
if context.interaction:
await context.interaction.response.send_message(embed=embed, view=view)
else:
await context.send(embed=embed, view=view)
return ios26

View File

@@ -13,6 +13,31 @@ class MelonxSelect(discord.ui.Select):
value="transfer", value="transfer",
description="How to transfer save files from other emulators or platforms", description="How to transfer save files from other emulators or platforms",
), ),
discord.SelectOption(
label="Mods",
value="mods",
description="How to install mods within MeloNX (Limited Support)",
),
discord.SelectOption(
label="Game Crash",
value="gamecrash",
description="Why does my game crash?",
),
discord.SelectOption(
label="Requirements",
value="requirements",
description="What does MeloNX require?",
),
discord.SelectOption(
label="Error",
value="error",
description="What does this error message mean?",
),
discord.SelectOption(
label="iOS 26",
value="26",
description="How can I run MeloNX on iOS 26?",
),
] ]
super().__init__(placeholder="Choose a MeloNX command...", options=options) super().__init__(placeholder="Choose a MeloNX command...", options=options)

47
cogs/melonx/mods.py Normal file
View File

@@ -0,0 +1,47 @@
import discord
from discord import app_commands
from discord.ext import commands
from discord.ext.commands import Context
import time
def mods_command():
@commands.hybrid_command(
name="mods", description="How to install mods within MeloNX (Limited Support)"
)
async def mods(self, context):
embed = discord.Embed(
color=0x963155,
description=(
'# How do I install mods within MeloNX? (Limited Support)\n\n---\n\n' +
'### **romFS/exeFS mods**:\n' +
'1. Obtain your title ID of your game by copying it from MeloNX, Hold down on the game and click game info.\n' +
'2. Copy it and then go to Files-> MeloNX-> mods-> contents\n' +
'3. In the contents folder create a new folder and name it the title ID you copied earlier.\n' +
'4. Now place all your mods for that game in the folder you just made (these should be folders with the mod name, do not mess with the file structure of the mod after unzipping it.)\n\n' +
'### **Atmosphere mods**: \n' +
'1. Obtain your title ID of your game by copying it from MeloNX, Hold down on the game and click game info.\n' +
'2. Copy it and then go to Files-> MeloNX-> sdcard-> atmosphere-> contents\n' +
'3. In the contents folder create a new folder and name it the title ID you copied earlier.\n' +
'4. Now place all your mods for that game in the folder you just made (these should be folders with the mod name, do not mess with the file structure of the mod after unzipping it.)'
)
)
embed.set_author(name="MeloNX", icon_url="https://yes.nighty.works/raw/TLGaVa.png")
embed.set_footer(text=f'Last Edited by neoarz')
embed.timestamp = discord.utils.utcnow()
view = discord.ui.View()
view.add_item(discord.ui.Button(
label="Edit Command",
style=discord.ButtonStyle.secondary,
url="https://github.com/neoarz/Syntrel/blob/main/cogs/melonx/mods.py",
emoji="<:githubicon:1417717356846776340>"
))
if context.interaction:
await context.interaction.response.send_message(embed=embed, view=view)
else:
await context.send(embed=embed, view=view)
return mods

View File

@@ -0,0 +1,42 @@
import discord
from discord import app_commands
from discord.ext import commands
from discord.ext.commands import Context
import time
def requirements_command():
@commands.hybrid_command(
name="requirements", description="What does MeloNX require?"
)
async def requirements(self, context):
embed = discord.Embed(
color=0x963155,
description=(
'# "What does MeloNX require?"\n\n---\n\n' +
'- JIT is **Mandatory**, because of this MeloNX will never be on the App Store / TestFlight\n' +
'- A Modded Nintendo Switch\n' +
'- The Increased Memory Limit Entitlement\n' +
'- A device with a **A12/M1** chip and **4GB Ram** or higher\n' +
'- TrollStore is supported with limited functionality for iOS 15'
)
)
embed.set_author(name="MeloNX", icon_url="https://yes.nighty.works/raw/TLGaVa.png")
embed.set_footer(text=f'Last Edited by neoarz')
embed.timestamp = discord.utils.utcnow()
view = discord.ui.View()
view.add_item(discord.ui.Button(
label="Edit Command",
style=discord.ButtonStyle.secondary,
url="https://github.com/neoarz/Syntrel/blob/main/cogs/melonx/requirements.py",
emoji="<:githubicon:1417717356846776340>"
))
if context.interaction:
await context.interaction.response.send_message(embed=embed, view=view)
else:
await context.send(embed=embed, view=view)
return requirements