Workflow Utilities Reference¶
erlc-api.py 2.3 adds workflow helpers for dashboards, Discord bots, and
multi-server tools. These modules are still lazy: import them explicitly only
when needed.
Location¶
Import:
Use LocationTools(data) with players, emergency calls, raw dictionaries, or a
ServerBundle.
bundle = await api.server(players=True, emergency_calls=True)
tools = LocationTools(bundle)
nearest = tools.nearest_players_to_call(bundle.emergency_calls[0], limit=3)
near_postal = tools.by_postal("218")
map_url = tools.official_map_url(season="fall", layer="postals")
Core methods:
| Method | Purpose |
|---|---|
point(value, z=None) |
Convert a model, mapping, position list, or x/z pair into Coordinate. |
distance(a, b) |
Euclidean distance between two coordinates. |
nearest(origin, items=None, limit=1, max_distance=None) |
Sorted LocationMatch results. |
within_radius(origin, radius, items=None) |
All location-capable items inside a radius. |
by_postal(postal_code) / by_street(street_name) |
Match v2 player location labels. |
official_map_url(season="fall", layer="postals") |
PRC official map image URL. |
Map overlays require Pillow:
MapRenderer().render_points(...) requires either bounds= or transform=
because the official API gives game X/Z coordinates, not a universal pixel
calibration.
Vehicle Tools¶
Import:
VehicleTools understands the typed vehicle catalog, PRC vehicle names,
owners, plates, colors, and textures.
bundle = await api.server(players=True, vehicles=True)
tools = VehicleTools(bundle.vehicles)
prestige = tools.prestige()
duplicates = tools.duplicate_plates()
avi_vehicles = tools.by_owner("Avi")
joined = bundle.player_vehicles
if joined is not None:
player_view = joined.player("Avi")
owned = player_view.vehicles if player_view else []
Core methods:
| Method | Purpose |
|---|---|
by_owner(query) |
Match owner name or user ID. |
by_team(players=...) |
Group vehicles by owner team using player data. |
by_color(color) / by_texture(texture) |
Match visual attributes. |
by_model(query) / by_name(query) |
Catalog-aware model/name search. |
find_plate(plate) / duplicate_plates() |
Normalize and inspect plates. |
abandoned(online_players) |
Vehicles whose owner is not currently online. |
primary() / secondary() / prestige() |
Catalog classification helpers. |
summary() |
Count by model, color, owner, and classification. |
See Vehicle Tools for parser and catalog details.
Emergency Calls¶
Import:
Use these helpers when building dispatch dashboards or responder bots.
bundle = await api.server(players=True, emergency_calls=True)
calls = EmergencyCallTools(bundle.emergency_calls)
unresponded = calls.unresponded()
nearest = calls.nearest_to(bundle.players[0])
summary = calls.summary()
Core methods:
| Method | Purpose |
|---|---|
active() |
Calls that are still active in the fetched payload. |
unresponded() |
Calls without assigned/responding player IDs. |
by_team(team) |
Police, sheriff, fire, EMS, or other team grouping. |
nearest_to(player_or_location) |
Sort calls by distance from a player/location. |
nearest_players_to_call(call, players=...) |
Find responders near a call. |
summary() |
Count total, active, unresponded, and by team. |
See Emergency Calls for call-specific examples.
Bundle Presets¶
Import:
Built-in presets:
| Preset | Includes |
|---|---|
minimal |
Server info only. |
players |
Players and queue. |
dashboard |
Players, staff, queue, vehicles, emergency calls. |
logs |
Join, kill, command, and mod logs. |
ops |
Operational bot state. |
all |
Every v2 include. |
Examples:
bundle = await AsyncBundle(api).dashboard()
ops = BundleRequest.preset("dashboard").include("command_logs")
bundle = await AsyncBundle(api).fetch(ops)
register_preset("dispatch", ["players", "emergency_calls", "vehicles"])
dispatch = await AsyncBundle(api).fetch("dispatch")
Rules¶
Import:
Rules evaluate data and return RuleMatch objects. They do not run PRC
commands.
engine = RuleEngine()
engine.add(
"queue-active",
Conditions.queue_length(at_least=1),
severity="info",
message="Queue is active",
)
matches = engine.evaluate(bundle)
Condition helpers cover player count, queue length, staff count, vehicle count, command names/prefixes, emergency-call age, and status severities.
Multi Server¶
Import:
Use named server refs so every result remains identifiable.
servers = [
ServerRef("main", "main-server-key"),
ServerRef("training", "training-server-key"),
]
manager = AsyncMultiServer(api, servers, concurrency=3)
results = await manager.status()
summary = await manager.aggregate()
Failures are collected per server by default. call(...) only allows read-only
client methods; command broadcasting must stay explicit in user code.
Discord Tools¶
Import:
These helpers return plain dictionaries compatible with most Discord libraries.
They do not import discord.py.
from erlc_api.status import StatusBuilder
status = StatusBuilder(bundle).build()
payload = DiscordFormatter().server_status(status).to_dict()
await channel.send(**payload)
Text is clipped to Discord limits and @everyone / @here mentions are made
safe.
For the full method reference, see Formatting, Analytics, and Export.
Diagnostics¶
Import:
Diagnostics turn wrapper objects into user-facing messages.
try:
await api.players()
except Exception as exc:
diagnostics = diagnose_error(exc)
print(diagnostics.to_dict())
Use diagnostics for logs, bot replies, and dashboards; keep catching typed exceptions for control flow.
Cache¶
Import:
The default cache is memory-only TTL. It caches read endpoints only and never
caches command(...).
cached = AsyncCachedClient(api, ttl_s=5)
players = await cached.players()
again = await cached.players() # served from cache for the same arguments
Applications that need custom stores can provide an adapter implementing the documented cache protocol.
Status¶
Import:
Status builders produce typed dashboard snapshots:
StatusBuilder(bundle).build() works with data you already fetched, avoiding
an extra HTTP call.
Command Flows¶
Import:
Flows preview and validate command sequences. They do not execute commands.
warn = CommandTemplate("warn", "warn {target} {reason}")
flow = (
CommandFlowBuilder("warn-and-pm")
.template(warn, target="Avi", reason="RDM")
.step("pm Avi Please review the rules")
.build()
)
print(flow.preview())
Common mistakes:
- Expecting rules or command flows to send PRC commands automatically.
- Using multi-server utilities for command broadcasting.
- Installing Pillow for geometry-only location helpers; it is only needed for rendered overlays.
- Caching command results.
CachedClientintentionally caches read methods only.
Related Pages¶
Previous Page: Ops Utilities Reference | Next Page: Formatting, Analytics, and Export