The 1024-char cap + empty substitute only ever applied to the Log field.
Action and Actor got no cap, so a long action/actor string (a real path -
e.g. a long command invocation string as the action) triggers Discord's
BASE_TYPE_MAX_LENGTH 400 on send; _send swallows that via log.exception and
returns None, silently losing the Discord message while the stdlib mirror
survives. Route all three fields through one _cap_field helper (single
source for the 1024 constant) instead of duplicating the cap logic.
Signed-off-by: disqualifier <dev@disqualifier.me>
The settings-lookup KeyError->ValueError raise was bare, unlike the three
sibling discord-exception normalization sites which all chain via
"from error". __context__ still linked implicitly at runtime, but this makes
the traceback style consistent (flake8-B904) across every normalization site.
Signed-off-by: disqualifier <dev@disqualifier.me>
The wrong-type channel check sat after the no-resolvable-guild guard, so a
non-TextChannel object passed without a guild raised the misleading "channel
provided without a resolvable guild" instead of "is not a text channel" - the
accurate message only fired when a guild was also supplied. Move the type
check first so both branches report the real problem.
Signed-off-by: disqualifier <dev@disqualifier.me>
a string timezone passed setup silently and TypeError'd on every send,
blackholing the sink; now validated as a real tzinfo in initialize().
a long pings list could push critical() content past Discord's 2000-char
limit, silently dropping the send; content is now capped to fit. also
compresses docstrings/comments with no behavior change.
Signed-off-by: disqualifier <dev@disqualifier.me>
initialize() previously let a bad construction channel id leak raw
discord.errors.NotFound/Forbidden/HTTPException past the documented
ValueError-only setup contract, and let an already-resolved non-TextChannel
object (Thread/VoiceChannel/ForumChannel) pass silently, later misrouting or
blackholing every send. Wrap the construction-channel fetch in the same
try/except as the settings path and type-check the resolved-object channel
path, mirroring the existing int-path guard.
Widened the normalization tuple to also catch discord.ClientException
(covers InvalidData), fixing dpylogger-9 opportunistically since it's the
same pattern.
Bump to v0.1.5.
Signed-off-by: disqualifier <dev@disqualifier.me>
- dpylogger-2: build_embed/_emit_stdlib test 'is not None' so falsy-but-valid values (0,
False) render; only None or '' is dropped/substituted.
- dpylogger-3: critical() delegates to _send (via a new content= param) instead of
hand-mirroring the send/error scaffolding — single source of truth.
verified vs discord.py 2.7.1. bump v0.1.2 -> v0.1.4
Signed-off-by: disqualifier <dev@disqualifier.me>
DPYLogger(guild=None, channel=<TextChannel>) passed initialize() (both int-guards skipped)
but then every send failed at _get_guild(None) and got swallowed — logs never reached
discord, no loud setup signal. now derive self.guild from the channel it already carries,
or raise loud at setup for a truly guild-less channel (mirroring the int-channel guard).
verified vs discord.py 2.7.1. bump v0.1.2 -> v0.1.3
Signed-off-by: disqualifier <dev@disqualifier.me>
the construction-channel int path now applies the same isinstance(TextChannel) check the
settings path enforces, so a Voice/Category/Forum channel fails loud at setup instead of
AttributeError-ing on .send later. settings-path fetch_channel discord exceptions
normalize to ValueError; README error contract updated to match.
Signed-off-by: disqualifier <dev@disqualifier.me>
- _get_guild catches discord.HTTPException (NotFound/Forbidden/HTTPException) from
fetch_guild and re-raises the lib's ValueError; the old 'if not resolved' branch was
unreachable since fetch_guild never returns None (L10)
- build_embed substitutes '(no message)' for empty details and truncates to 1024, so a
logging call never 400s the embed send on an empty/over-long message (L11).
Signed-off-by: disqualifier <dev@disqualifier.me>
the original task() accepted an actor kwarg and ignored it (task actions are always attributed to SYSTEM/TASK); the rewrite dropped the param, so live callers passing task(..., actor=...) hit a TypeError. added actor=None back, accept-and-ignore, behavior unchanged. bump to v0.1.1. (feed() stays out of the base by design — consumers subclass.)
Signed-off-by: disqualifier <dev@disqualifier.me>
the README Errors section claimed resolution raises ValueError 'at call time', but per-call resolution is swallowed with send failures and the raise happens at initialize() — and the raised type can be an underlying discord exception (NotFound/Forbidden/HTTPException), not only ValueError. corrected to match the code and the module docstring.
Signed-off-by: disqualifier <dev@disqualifier.me>
the module docstring said resolution failures raise 'at initialize/call time', but per-call send-path resolution failures are swallowed with send failures (the documented intentional swallow). corrected to state resolution raises from initialize() at setup, while a per-call guild= that doesn't resolve falls back to stdlib like any send failure.
Signed-off-by: disqualifier <dev@disqualifier.me>
_get_channel compared guild == self.guild; when initialize() was not called, self.guild stays an int while the passed guild is a Guild object, so the comparison was always False and routing silently fell through to the bot.settings lookup instead of using the constructed channel. now compares by .id on both sides.
Signed-off-by: disqualifier <dev@disqualifier.me>