SDK Functions
Every name listed here is exported from moo.sdk and importable in
verb code (from moo.sdk import lookup, create, ...). For methods
defined on the Object model and accessible as obj.<name>(...),
see Objects in the DjangoMOO Database. For Property and Verb field reference, see
Properties on Objects and Verbs on Objects.
Object lifecycle and lookup
- moo.sdk.lookup(x, return_first=True)
Lookup an object within the current site by PK, name, or alias.
PK lookups are site-scoped: an integer PK that belongs to a different universe raises
NoSuchObjectErrorthe same as a missing object would. Internal system code that genuinely needs cross-site access should useObject.global_objectsdirectly rather than going through this function.- Parameters:
x (
Union[int,str]) – lookup valuereturn_first (
bool) – when True (default), return the first match or raise NoSuchObjectError; when False, return a list of all matches (may be empty)
- Returns:
the result of the lookup, or a list when return_first is False
- Return type:
- Raises:
NoSuchObjectError – when a result cannot be found and return_first is True
- moo.sdk.create(name, *a, **kw)
Creates and returns a new object whose parents are parents and whose owner is as described below. Provided parents are valid Objects with derive permission, otherwise
PermissionErroris raised. After the new object is created, its initialize verb, if any, is called with no arguments.The owner of the new object is either the programmer (if owner is not provided), or the provided owner, if the caller has permission to entrust the object.
If the intended owner of the new object has a property named ownership_quota and the value of that property is an integer, then create() treats that value as a quota. If the quota is less than or equal to zero, then the quota is considered to be exhausted and create() raises
QuotaErrorinstead of creating an object. Otherwise, the quota is decremented and stored back into the ownership_quota property as a part of the creation of the new object.- Parameters:
- Returns:
the new object
- Return type:
- Raises:
PermissionError – if the caller is not allowed to derive from the parent
QuotaError – if the caller has a quota and it has been exceeded
- moo.sdk.players()
Return a list of all player avatar Objects.
- Returns:
Objects that are player avatars
- Return type:
list[Object]
- moo.sdk.connected_players(within=None)
Return a list of player avatars whose
last_connected_timeproperty was updated within the given within window (default: 5 minutes).The
last_connected_timevalue is precached into the session-level property cache on every returned Object so subsequentget_propertycalls incur no extra queries.- Parameters:
within (timedelta) – recency window; defaults to
timedelta(minutes=5)- Returns:
Objects whose avatars have connected recently
- Return type:
list[Object]
- moo.sdk.owned_objects(player_obj)
Return a QuerySet of all Objects owned by player_obj, ordered by name.
- Parameters:
player_obj – the owner Object
- Return type:
QuerySet
- moo.sdk.owned_objects_by_pks(pk_list)
Return a QuerySet of Objects with PKs in pk_list, ordered by name.
Used by continuation tasks (e.g.
audit_batch) where the target player is not in scope but the remaining PK list was passed asargs[0].- Parameters:
pk_list – list of integer Object PKs
- Return type:
QuerySet
- moo.sdk.ensure_player_record(obj)
Ensure a
Playerrow exists for obj withuser=None.Used by NPC initialization so the avatar reports
is_player() == Trueto the parser whileis_connected() == Falsecausestell()to silently drop (no connection). Idempotent: returns the existing Player if one already references this avatar.- Parameters:
obj – the avatar Object
- Returns:
the Player row (created or pre-existing)
- Raises:
UserError – if the current caller is not a wizard
- moo.sdk.remove_player_record(obj)
Delete any anonymous (
user=None)Playerrows pointing at obj.Counterpart to
ensure_player_record(); used by the$npc.recycleverb. Rows tied to a realUserare left alone — those belong to a human player and removing them is not this helper’s job.- Parameters:
obj – the avatar Object
- Returns:
number of Player rows deleted
- Raises:
UserError – if the current caller is not a wizard
Tasks and continuations
- moo.sdk.invoke(*args, verb=None, callback=None, delay=0, periodic=False, cron=None, _caller=None, _player=None, **kwargs)
Asynchronously execute a Verb, optionally returning the result to another Verb. This is often a better alternative than using __call__-syntax to invoke a verb directly, since Verbs invoked this way will each have their own timeout.
- Parameters:
verb (Verb) – the Verb to execute
callback (Verb) – an optional callback Verb to receive the result
delay (
int) – seconds to wait before executing, cannot be used with cronperiodic (
bool) – should this task continue to repeat? cannot be used with croncron (
str|None) – a crontab expression to schedule Verb execution_caller – explicit caller override; falls back to
context.caller. Used bytransaction.on_commitcallbacks that fire after theContextManagerhas exited and cleared the contextvars._player – explicit player override; falls back to
context.player. Same reason as_caller.args – positional arguments for the Verb, if any
kwargs – keyword arguments for the Verb, if any
- Returns:
a
PeriodicTaskinstance or None if the task is a one-shot- Return type:
Optional[
PeriodicTask]
- moo.sdk.cancel_scheduled_task(pk)
Delete a
django_celery_beat.PeriodicTaskrow by primary key.Used by daemon lifecycle verbs (
$daemon.disable,$daemon.recycle) to remove the PT created byinvoke()(periodic=True). Idempotent: returnsFalseif no PT with that pk exists.- Parameters:
pk (
int) – thePeriodicTask.pkreturned byinvoke()- Return type:
bool- Returns:
Trueif a row was deleted,Falseif not found- Raises:
UserError – if the current caller is not a wizard
- moo.sdk.get_scheduled_task_info(pk)
Look up runtime stats for a scheduled task created by
invoke().Returns
Noneif noPeriodicTaskexists with the given pk (useful for orphan-pointer detection on daemon Objects).- Parameters:
pk (
int) – thePeriodicTask.pkto inspect- Return type:
dict|None- Returns:
dict with
enabled,last_run_at,total_run_count,interval_seconds(orNone), andtask(the Celery task name) — orNoneif not found.- Raises:
UserError – if the current caller is not a wizard
- moo.sdk.task_time_low(threshold=0.5)
Return
Trueif the current task’s remaining time is at or below threshold seconds.Always returns
Falsewhen there is no task-time limit (e.g. in tests or interactive shells without a configured limit).- Parameters:
threshold – seconds remaining before considering time low (default 0.5)
- Return type:
bool
- moo.sdk.schedule_continuation(remaining_items, verb, msg=None)
Schedule a continuation task carrying the PKs of remaining_items and notify the current player.
Intended for use inside long-running verbs that iterate over many objects. The continuation verb (e.g.
audit_batch,reload_batch) receivesargs[0]as the list of PKs and dispatches onverb_name.Usage:
for i, item in enumerate(items): if task_time_low(): schedule_continuation(items[i:], this.get_verb("audit_batch")) return # ... process item
- Parameters:
remaining_items – iterable of Objects (or any model with
.pk)verb – Verb instance to invoke for the continuation
msg – optional override for the progress message shown to the player
- moo.sdk.set_task_perms(who)
Set the task permissions to those of who for the duration of the with-block. :type who: :param who: the Object whose permissions to assume :type who: Object
- moo.sdk.moo_eval(code_string)
Evaluate arbitrary Python code in the RestrictedPython sandbox.
The code runs with the same environment as verb code, with standard verb variables (this, _, context) automatically available.
- Parameters:
code_string (
str) – Python code to evaluate- Returns:
The result of the evaluation
- moo.sdk.invoked_verb_name(default=None)
Return the verb name as the player typed it (lowercased), or
defaultwhen there is no active parser context.Verbs called via
moo.sdk.invoke(), async callbacks, or test harnesses have no parser; pass the sandbox-injectedverb_nameasdefaultto fall back to the verb’s defined name.- Return type:
str|None
Output and full-screen UIs
- moo.sdk.write(obj, message)
Send an asynchronous message to the user.
- Parameters:
obj (Object) – the Object to write to
message (Any) – any pickle-able object
- moo.sdk.open_editor(obj, initial_content, callback_verb, *args, content_type='text', title=None)
Request the connected SSH client to open a full-screen text editor. When the user saves, the edited text is passed to callback_verb as args[0], followed by any extra positional arguments supplied here. If the user cancels, the callback is not invoked.
- Parameters:
obj – the player Object whose client should open the editor
initial_content (
str) – text to pre-populate the editor buffercallback_verb – Verb to invoke with the edited text as args[0]
args – additional arguments forwarded to the callback verb as args[1:]
content_type (
str) – “python”, “json”, or “text” (default); controls syntax highlighting
- moo.sdk.open_paginator(obj, content, content_type='text')
Request the connected SSH client to open a full-screen read-only paginator. The user can scroll through the content and press Q to quit.
In raw-mode sessions (MUD clients, line-oriented terminals) the SSH server intercepts the paginator event and writes the content directly to the terminal instead of opening the interactive UI.
- Parameters:
obj – the player Object whose client should open the paginator
content (
str) – text to displaycontent_type (
str) – “python”, “json”, or “text” (default); controls syntax highlighting
- moo.sdk.can_open_editor()
True if the current player’s client can display an editor.
Either the player is in
richmode (prompt_toolkit TUI), or their client advertises support for the GMCPEditorpackage viaCore.Supports.Set(the djangomoo Mudlet bridge does this; the server hands the edit off to the client’s preferred local editor over GMCP). Verbs that open the editor should gate on this rather thanget_client_mode() == "raw"so bridge-equipped MUD clients are not forced onto the inlinewith "..."fallback.- Return type:
bool
Session settings and client capabilities
- moo.sdk.get_client_mode()
Return the current player’s shell mode.
Returns
"rich"(prompt_toolkit TUI, the default) or"raw"(line- based I/O for traditional MUD clients that cannot handle cursor control).Verbs use this to short-circuit editor-opening code paths in raw mode and suggest the inline
@edit ... with "..."form instead. Most verbs should callcan_open_editor()instead, which also returnsTruefor raw-mode clients that advertise GMCP Editor support (e.g. the djangomoo Mudlet bridge).- Return type:
str
- moo.sdk.get_wrap_column()
Return the effective wrap column for the current player.
Reads the player’s
wrap_columnproperty. If it is"auto"(or the property is not set), returns theterminal_widthsession setting, falling back to 80 if the terminal width is not known.
- moo.sdk.get_session_setting(key, default=None)
Get a session-specific output setting for the current player.
Session settings are stored per-user and cleared on disconnect. Used by PREFIX, SUFFIX, OUTPUTPREFIX/SUFFIX, and the
a11yverb.Checks the in-process
_session_settingsdict first (authoritative in the SSH server process and in tests), then falls back to the Django cache so Celery workers — which run in a separate process — can also read the value.- Parameters:
key – setting name (‘output_prefix’, ‘output_suffix’, ‘quiet_mode’, ‘color_system’)
default – value to return if setting is not found
- Returns:
setting value or default
- moo.sdk.set_session_setting(key, value)
Set a session-specific output setting for the current player.
Session settings are stored per-user and cleared on disconnect. Used by PREFIX, SUFFIX, OUTPUTPREFIX/SUFFIX, and the
a11yverb.Writes to the Django cache (accessible cross-process from Celery workers) and also publishes a
session_settingevent to the player’s Kombu queue so the SSH server’sprocess_messages()loop can update its own registry.- Parameters:
key – setting name (‘output_prefix’, ‘output_suffix’, ‘quiet_mode’, ‘color_system’)
value – setting value
Out-of-band MUD-client protocols
- moo.sdk.send_gmcp(obj, module, data=None)
Send a GMCP event to
obj’s SSH channel.GMCP (Generic MUD Communication Protocol) is the canonical OOB channel for structured MUD events. Clients that negotiated GMCP receive
IAC SB GMCP <module> <json> IAC SE; clients that did not see it as zero bytes on the wire (the SSH server skips the emit if the capability flag is false).Example:
send_gmcp(player, "Char.Vitals", {"hp": 50, "maxhp": 100}) send_gmcp(player, "Room.Info", {"num": 12, "name": "A dim hall"}) send_gmcp(player, "Core.Ping") # no payload
- Parameters:
obj – the Object (player avatar) to send the GMCP event to
module (
str) – GMCP module/package name, e.g."Char.Vitals"data – JSON-serializable value, or
Nonefor an empty event
- moo.sdk.play_sound(obj, name, volume=100, priority=10)
Play a sound on
obj’s client.Prefers GMCP
Client.Media.Playwhen the client negotiated GMCP; falls back to the inline MSP!!SOUND(...)marker if the client negotiated MSP; no-ops otherwise.DjangoMOO does not bundle any sound assets. Sound pack authors are expected to provide filenames that their client-side pack can resolve.
- Parameters:
obj – the player to play the sound on
name (
str) – filename (client-resolvable), e.g."door.wav"volume (
int) – 0–100priority (
int) – higher numbers preempt lower-priority sounds
- moo.sdk.room_info_payload(room)
Build the IRE-style GMCP
Room.Infopayload forroom.Returns
{"num", "name", "exits"}with values stringified per the Achaea/Aardwolf/Mudlet-generic-mapper convention. Exit keys are normalized to short codes (n,ne,u, …); custom-named exits ("ladder","portal") round-trip unchanged so they still appear on the client.DjangoMOO names cardinal exits
"<direction> from <room>"— e.g."east from grand foyer"— to keep them globally unique. We check the exit’s exact name, then its first word, then its aliases for a direction match before falling back to the raw name.- Parameters:
room – an Object representing a room
- Return type:
dict- Returns:
a dict suitable for
send_gmcp(player, "Room.Info", payload)
Server administration
- moo.sdk.boot_player(obj)
Disconnect the given player from the MOO server.
Publishes a
disconnectevent to the player’s Kombu message queue, which the SSH server’sprocess_messages()loop picks up and exits cleanly.Permission: the caller must be the player being booted, or a wizard.
- Parameters:
obj – the player Object to disconnect
- moo.sdk.server_info()
Return a dict with server version and process statistics.
Keys:
version,python,pid,memory_mb(may beNoneon platforms whereresourceis unavailable).- Return type:
dict
Mail Functions
- moo.sdk.send_message(sender, recipients, subject, body)
Create a message and deliver it to all recipients.
- Parameters:
sender – the sending Object (must be a player)
recipients (
list) – list of recipient Objects (must be players)subject (
str) – message subject linebody (
str) – message body text
- Returns:
the created Message instance
- moo.sdk.get_mailbox(player, include_deleted=False)
Return player’s received messages as a list of MessageRecipient rows, newest first.
- Parameters:
player – the recipient Object
include_deleted (
bool) – if True, include soft-deleted messages
- Return type:
list- Returns:
list of MessageRecipient instances
- moo.sdk.get_message(player, n)
Return the nth message (1-based) in the player’s non-deleted mailbox, or None.
- Parameters:
player – the recipient Object
n (
int) – 1-based message index
- Returns:
MessageRecipient or None
- moo.sdk.mark_read(player, n)
Mark message n as read. Returns True if successful, False if n is out of range.
- Return type:
bool
- moo.sdk.delete_message(player, n)
Soft-delete message n. Returns True if successful, False if n is out of range.
- Return type:
bool
- moo.sdk.undelete_message(player, n)
Restore the nth deleted message (1-based among deleted-only list). Returns True if successful, False if n is out of range.
- Return type:
bool
- moo.sdk.count_unread(player)
Return the count of unread, non-deleted messages for the player.
- Return type:
int
- moo.sdk.get_mail_stats(player)
Return a dict with
total,unread, anddeletedmessage counts for the player. All counts are computed in two queries.- Return type:
dict