Skip to content

About

This is one of the official nighty docs, you can find anything you need in here. Good luck!

Resources

Stars

13 stars

Watchers

1 watching

Forks

Latest commit

 

History

21 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

NightyScript Documentation

Version 5.1

Public reference for Nighty scripts, native UI scripting, slash commands, Discord Components V2, and CUI.

Documentation version Python version UI scripting Slash commands Components V2 CUI

Quick start · Documentation · Examples · Troubleshooting

Maintained by: rico · 1361736124858630274


Note

Nighty injects its scripting objects at runtime. Do not install or import nighty or discord.py inside a NightyScript.

Documentation

Guide Covers
Python 3.14 runtime Version support, compatibility changes, dependencies, and local checks
Native UI scripting Tabs, containers, cards, groups, controls, tables, callbacks, and responsive layouts
Native slash commands Typed options, groups, autocomplete, themed replies, and sync
Discord Components V2 Native layouts, containers, buttons, sections, and callbacks
CUI and custom tabs Custom HTML elements, callbacks, pagination, and browser reloads
Reload-safe scripts Tasks, listeners, sockets, cleanup, and shared runtime state
Troubleshooting Common load, interaction, CUI, storage, and event-loop failures
Example scripts Complete files ready to inspect and adapt

Quick start

1. Understand the runtime

Nighty 2.6.2 runs scripts on Python 3.14 inside its own process. Nighty supplies bot, bot_app, nightyScript, Tab, UI, configuration helpers, theme helpers, and Discord objects.

Do not import Nighty or Discord packages:

# Unsupported
import discord
import nighty
from discord import *
from nighty import *

Use standard-library imports and Python 3.14-compatible dependencies documented by the script. Keep imports inside the decorated function when Nighty callbacks need them. Nighty may execute a script with separate global and local namespaces. Read Python 3.14 runtime compatibility before adding a package.

2. Start with the script wrapper

@nightyScript(
    name="Channel Notes",
    author="rico",
    description="Save a note for the current channel",
    usage="<p>channelnote <text>"
)
def channel_notes():
    """
    CHANNEL NOTES

    COMMANDS:
    <p>channelnote <text> - Save a note for the current channel
    """

    @bot.command(
        name="channelnote",
        usage="<text>",
        description="Save a note for the current channel"
    )
    async def channel_note(ctx, *, text: str):
        await ctx.message.delete()
        updateConfigData(f"channel_note_{ctx.channel.id}", text.strip())
        await ctx.send("Saved the channel note.", silent=True)

channel_notes()

Call the decorated function at the end of the file. Nighty will not register the script until that call runs.

3. Pick the right interface

  • Use @bot.command for prefix commands.
  • Use @slashCommand for native application commands.
  • Use Tab and UI for native Nighty settings pages.
  • Add CUI when a native page needs a custom control or overlay.
  • Use Components V2 for structured Discord interaction responses.

Core reference

Configuration

Use Nighty's configuration store for booleans, strings, and numbers:

enabled = getConfigData().get("channel_notes_enabled", True)
updateConfigData("channel_notes_enabled", False)

Prefix keys with the script name. This prevents collisions with other scripts.

JSON storage

Use a JSON file for lists and nested data:

from pathlib import Path
import json

DATA_DIR = Path(getScriptsPath()) / "json"
DATA_FILE = DATA_DIR / "channel_notes.json"

def load_notes():
    DATA_DIR.mkdir(parents=True, exist_ok=True)
    try:
        with DATA_FILE.open("r", encoding="utf-8") as file:
            data = json.load(file)
        return data if isinstance(data, dict) else {"notes": {}}
    except (FileNotFoundError, json.JSONDecodeError, OSError):
        return {"notes": {}}

def save_notes(data):
    DATA_DIR.mkdir(parents=True, exist_ok=True)
    try:
        with DATA_FILE.open("w", encoding="utf-8") as file:
            json.dump(data, file, indent=2, ensure_ascii=False)
        return True
    except OSError as error:
        print(f"[Channel Notes] Save error: {error}", type_="ERROR")
        return False

Store tokens and webhook URLs outside source files. Do not commit runtime JSON files.

Prefix commands

@bot.command(
    name="quote",
    aliases=["q"],
    usage="<message>",
    description="Send a quoted message"
)
async def quote_command(ctx, *, message: str):
    await ctx.message.delete()
    message = message.strip()
    if not message:
        await ctx.send("Add a message to quote.", silent=True)
        return
    await ctx.send(f"> {message}")

<p> in usage text represents the prefix set in Nighty. Scripts do not parse the prefix.

Use one command with subcommands when the actions share a purpose:

@bot.command(name="notes", usage="<add|list|clear> [text]")
async def notes_command(ctx, *, args: str = ""):
    await ctx.message.delete()
    action, _, value = args.strip().partition(" ")
    action = action.lower()

    if action == "add" and value.strip():
        await ctx.send(f"Saved: {value.strip()}", silent=True)
    elif action == "list":
        await ctx.send("No saved notes.", silent=True)
    elif action == "clear":
        await ctx.send("Cleared saved notes.", silent=True)
    else:
        await ctx.send("Use `notes add`, `notes list`, or `notes clear`.", silent=True)

Event listeners

@bot.listen("on_message")
async def message_listener(message):
    if message.author.id == bot.user.id:
        return
    if getattr(message.author, "bot", False):
        return
    if "good morning" in message.content.lower():
        await message.channel.send("Good morning.", silent=True)

Filter events before network calls or file access. A listener runs for each matching Discord event.

Nighty keeps the Python process alive during script reloads. Scripts with listeners, tasks, or Socket.IO callbacks need cleanup code. Read Reload-safe scripts.


Messages

Plain text

await ctx.send("Saved.", silent=True)
await message.channel.send("New event received.", silent=True)

Legacy Nighty embed

Nighty does not support discord.Embed in standard scripts. Use forwardEmbedMethod:

await forwardEmbedMethod(
    channel_id=ctx.channel.id,
    title="Build report",
    content="**Status:** Passed\n**Checks:** 12",
    image="https://example.com/report.png"
)

Supported arguments are channel_id, title, content, and image.

Components V2

Components V2 supports containers, text displays, sections, media, and interactive controls. Use a discord_bot.ui.LayoutView when slashReply() does not provide the layout you need. Read Discord Components V2.

Native slash commands

Nighty registers application commands with @slashCommand and sends themed replies with slashReply().

@slashCommand(name="status", description="Show the script status")
async def status(interaction: discord_bot.Interaction):
    await slashReply(interaction, "Status: ready")

Nighty syncs command changes after the script loads. Read Native slash commands for options, subcommands, autocomplete, and custom Components V2 layouts.

Native UI scripting

Nighty's native UI uses this hierarchy:

Tab
└── CardContainer
    └── Card
        ├── Group
        └── UI element
tab = Tab(name="Task Queue", icon="inbox", gap=4)
container = tab.create_container(type="rows", width="full", height="auto", gap=4)
card = container.create_card(width="full", height="auto", gap=3)

card.create_ui_element(UI.Text, content="Task Queue", size="lg", weight="bold")
task_input = card.create_ui_element(
    UI.Input,
    label="Task",
    placeholder="Enter a task",
    full_width=True
)
save_button = card.create_ui_element(UI.Button, label="Save", color="primary")

async def save_task():
    value = str(task_input.value or "").strip()
    if not value:
        tab.toast("Task required", "Enter a task name.", "ERROR")
        return
    tab.toast("Task saved", value, "SUCCESS")

save_button.onClick = save_task
tab.render()

Read Native UI scripting for the full component reference, callbacks, tables, validation, responsive layouts, and debugging.

CUI extensions

CUI adds custom HTML elements and callable overlays without changing the native parent creation rules. Use it for controls that Nighty's built-in UI classes do not provide. Read CUI and custom tabs.


Runtime safety

Async work

Use aiohttp for network requests:

import aiohttp

async def fetch_json(url):
    timeout = aiohttp.ClientTimeout(total=15)
    async with aiohttp.ClientSession(timeout=timeout) as session:
        async with session.get(url) as response:
            response.raise_for_status()
            return await response.json()

Move blocking libraries to an executor:

async def run_blocking(function, *args):
    loop = asyncio.get_running_loop()
    return await loop.run_in_executor(None, lambda: function(*args))

Use asyncio.sleep() inside async functions. time.sleep() blocks Nighty's event loop.

Logging

print("[Task Queue] Loaded 12 tasks", type_="INFO")
print("[Task Queue] Save failed", type_="ERROR")
print("[Task Queue] Sync complete", type_="SUCCESS")

Include the script name and the failed operation. Keep tokens, cookies, and webhook URLs out of logs.

Example scripts

v5 examples

Existing examples

The example-scripts directory also covers JSON storage, configuration, event listeners, API clients, webhooks, selectors, tables, voice-message downloads, and browser automation.

Limits

  • Nighty scripts cannot build a complete cross-server user database.
  • User and member access depends on Discord cache state and channel access.
  • Native slash commands depend on Nighty's application bot connection and Discord registration.
  • CUI runs in Nighty's browser page. A browser refresh creates a new JavaScript window.
  • Discord rate limits apply to messages, command syncs, and interaction callbacks.

Troubleshooting

Start with the dedicated troubleshooting guide. It covers script load failures, missing slash commands, expired interactions, raw CUI placeholders, browser refresh problems, JSON write errors, and event-loop failures.

When reporting a bug, include:

  • the full Nighty console error;
  • the action that caused it;
  • whether the script was freshly loaded or reloaded;
  • whether Nighty Desktop or the web interface was used;
  • the smallest script that still reproduces it.

Credits

License

Released under the GNU General Public License v3.0.

NightyScript Documentation v5.0
Back to top

About

This is one of the official nighty docs, you can find anything you need in here. Good luck!

Resources

Stars

13 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages