-
v2.1.0
Stablereleased this
2026-09-26 11:08:13 -05:00 | 46 commits to main since this releaseAdded
- Terror Zone alerts delete themselves when the zone rotates out. The
channel shows only the current zone, not a stack of old ones whose "Next
Rotation" reads "3 hours ago". An alert that pinged too many people for one
message is deleted in full. DClone and walk alerts stay up.- A restart doesn't leave any behind. Each alert is saved in a new
d2emu_tz_alertstable (migration 012, applied at boot) with the time its
rotation ends. The first poll after a restart deletes the ones that ended
while the bot was down. - A failed delete is retried every poll for two hours past the rotation,
then given up on with awarn(d2emu/poll). One someone already deleted
by hand is just forgotten.
- A restart doesn't leave any behind. Each alert is saved in a new
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- Terror Zone alerts delete themselves when the zone rotates out. The
-
v2.0.1
Stablereleased this
2026-09-25 17:19:32 -05:00 | 47 commits to main since this releaseFixed
-
Hosted-walk alerts read far more Clone Hunters posts. Checked against
every one of their posts this server has received (149, April to
September), 2.0.0 could read only 62. It now reads 113:- "Region: NA" reads as USA. It's the word they use most, including on
the weekly softcore non-ladder walks, and 2.0.0 didn't know it. - "Region(s):" counts as a Region line.
- Every Region line counts, so a post announcing a USA walk and an EU
walk pings both. - Follow-ups with no Region line ("Walk NOW EU", "ASIA ROTW SCL NOW GET
IN A GAME", "bonus walk … on Asia") have their region read from the rest
of the text. The short codes (NA, EU, KR) only count in capitals, so
ordinary prose isn't read as a region.
The other 36 name no region ("Region: TBD", "We are done for the day",
ladder-reset notices) and still ping nobody. - "Region: NA" reads as USA. It's the word they use most, including on
Changed
- The walk reply is worded as a post, not a walk: "Clone Hunters post for
ROTW SC Ladder in EU", plus the post's times. It sits right under a
post that may just as well be a reminder, a time change or a cancellation. - A tagged post that names no region logs at
info, notwarn. That's
ordinary. Thewarnnow means something the catalog may be missing: no
known tag, or a Region line with no word it knows.
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
-
-
v2.0.0
Stablereleased this
2026-09-25 09:09:28 -05:00 | 48 commits to main since this releaseD2 alerts now go only to the people who signed up for them. This is a major
release because four things existing users rely on change. After deploying,
run/aufadmin d2 signup-boardand pin the message it posts.Changed
- Terror Zone alerts stop until someone signs up. Every rotation used to
post for everyone in the channel. Now each person picks their zones with
/aufhocker d2 tz-alerts, and a rotation pings only the people who picked
that zone. If nobody in the server picked it, the bot posts nothing. - DClone alerts stop until someone signs up.
/aufhocker d2 dclone-alerts
picks game modes (softcore or hardcore, ladder or non-ladder) and regions
(USA, EU, KR). A progress change pings the people who picked that game's
mode and its region, and the post lists only the games someone in the
server signed up for. /aufhocker d2 channelis now/aufadmin d2 notifications-channel, with
the same option and the same view-or-set behaviour. The D2 admin commands
now live together under/aufadmin, which only admins can see.D2EMU_TZ_NOTIFY_AREA_IDSno longer does anything. It was one zone list
for the whole server, and sign-ups replace it. Nothing carries over from
it, so everyone signs up fresh. If it's still set, the bot logs a warning at
boot; remove it from the stack file.
Added
- Sign-up menus.
tz-alertsshows one dropdown per act, and
dclone-alertsandwalk-alertsshow a mode dropdown and a region
dropdown. Each menu is private, opens with your current picks ticked, and
saves the moment a dropdown changes. For DClone and walks, it warns you when
modes or regions are empty, because a ping needs both. Untick everything to
stop. Sign-ups are per server. - A sign-up board.
/aufadmin d2 signup-boardposts one message in the D2
channel with a button for each menu. It's the same message for everyone and
never shows anyone's picks, and its buttons keep working after a restart. - Hardcore and non-ladder DClone. The bot now tracks all twelve Reign of
the Warlock games instead of the three softcore ladder ones, at no extra API
cost, since they all come back in the one response./aufhocker d2 dclone
lists all twelve. - Hosted-walk alerts. When D2R Clone Hunters announce a walk in their
#announcements, which this server follows, the bot replies under the
copied post and pings the people signed up for that mode and region with
/aufhocker d2 walk-alerts. The copied post's own role mention arrives as
plain text and never pinged anyone. A post the bot can't read pings nobody
and logs a warning with its text. Walk alerts are on when
D2EMU_WALK_SOURCE_CHANNEL_IDis set (Clone Hunters'#announcements,
895727392092459049, in.env.config). Leave it empty and they're off. - Tip: set the D2 channel to Only @mentions.
d2 help, the menus and the
board all say so. From then on, the only D2 alerts that reach you are the
ones you picked. - The
d2emu_subscriptionstable (migration 011), and thed2emu/subsand
d2emu/walkslog phases. - Plugin contract:
buildAdminCommands/handlesAdminSlash/
handleAdminSlashlet a plugin add one group to/aufadmin.
handleSelectMenuroutes string select menus the wayhandleButtonroutes
buttons, bycomponentPrefix(renamed frombuttonPrefix).onCrosspost
hands plugins messages copied in from a followed channel, which the context
store never sees. Seedocs/PLUGINS.md.
Fixed
- A DClone walk no longer swallows another game's progress. When one game
walked and another moved in the same poll, only the walk was posted. Now
both are. With twelve games tracked, that happens often.
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- Terror Zone alerts stop until someone signs up. Every rotation used to
-
v1.23.0
Stablereleased this
2026-09-24 23:36:51 -05:00 | 49 commits to main since this releaseAdded
-
Follow-up questions remember the conversation.
/aufhocker query-chat
and/aufhocker espnff mcpused to start from nothing on every question, so
"what about next week?" had no idea what came before it. Now a question
asked within an hour of your previous one is sent with the questions and
answers before it. Each person gets their own conversation, per channel and
per command.new:Trueon either command starts over, and so does an hour
of silence or a conversation reaching 20 questions (every follow-up re-sends
the whole thing, so it cannot grow forever).A follow-up adds only what was said in the channel since the previous
question, rather than re-reading the last hour. Passingcontext:on a
follow-up still pulls that window, because asking for it is asking for it.Conversations live in a new
conversation_turnstable and are deleted as a
whole once their last question is older than the memory window. Set
CONVERSATION_MEMORY_MINUTESin.env.config(default60;0turns
memory off and brings back the old behaviour). -
Follow-ups are cached, so they stay cheap. Each conversation request
marks the end of the new question as a prompt-cache breakpoint, so the next
follow-up reads every earlier turn at about a tenth of the normal input
price. The cache lastsPROMPT_CACHE_TTL(default1h, matched to the
memory window;5mis the other option). Saving to the 1-hour cache costs
twice the normal input price once, so a question that never gets a
follow-up costs a little more than before, and every follow-up costs much
less. The cache only hits if the replayed turns are byte-for-byte what was
sent before, so each turn is stored exactly as it went out. The
claude/apisuccess line now logscacheReadInputTokens, the number that
shows whether it is working. -
Public answers become shared context. Pressing 📢 Make Public now also
records the answer, and every public answer in a channel is context for
everyone's next question there.query-chatsees them interleaved with the
chat.espnff mcpsees them and nothing else: it still never reads the
chat, and its prompt treats them as possibly out of date, with the fantasy
tools as the source of truth. Private answers never leave the asker's own
conversation. Public answers sit in a newpublic_answerstable and follow
RETENTION_DAYSlike chat. A long answer is trimmed to 1,500 characters in
context so one answer cannot crowd out the rest of the history. -
/aufhocker help, plus/aufhocker lol helpand/aufhocker d2 help
alongside the existingespnff help. There was no way to find out what the
bot could do from inside Discord except typing/aufhockerand reading
one-line descriptions. The general help lists every command that is turned
on (lol and d2 only appear when enabled) and points at each group's own
help. The group helps list their commands, show admin-only commands only to
admins, and answer even while the feature is off, saying so, since every
other command in the group refuses then.espnff helpnow also mentions
follow-ups and that it reads public answers.
Changed
- README corrected. The usage section still showed
/aufhocker query:<question>, which has not been the command for a long time (it is
/aufhocker query-chat query:<question>), and did not mentionespnffat
all. Both are fixed, and follow-ups, public answers, help and the two new
settings are documented.
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
-
-
v1.22.0
Stablereleased this
2026-09-17 15:34:57 -05:00 | 50 commits to main since this releaseAdded
-
/aufhocker d2 tzand/aufhocker d2 dclonenow offer a "📢 Make Public" button, the same one the Claude commands have had. Both answers still arrive as a whisper, so checking the Terror Zone or DClone progress never spams a channel by itself, but the person who ran the command can now put the embed in the channel with one click instead of screenshotting it.The rules match the query plugin's flow exactly, because they are the security-sensitive part: only the user who ran the command may publish its answer, and a pending answer expires after an hour so a stale whisper cannot be dropped into a channel long after the numbers it quotes went out of date. Publishing clears the whisper, so the embed is never on screen twice with a live button on the stale copy.
Error embeds get no button. There is nothing worth sharing in "the API is down", and a button on it is one more way to spam a channel.
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
-
-
released this
2026-09-16 13:35:29 -05:00 | 51 commits to main since this releaseChanged
-
A missed MCP server is retried instead of given up on. The bot asks
every server inMCP_SERVERSfor its tools once, at startup, and a server
that did not answer was then missing for the life of the process. The case
that hits is the cheap one: the bot and theespnffserver are containers
on the same host and they start together, so the bot can lose the race by a
few seconds and then run for days with/aufhocker espnff mcprefusing
every question. Nothing in Discord announced it — the first sign was a
fantasy question refused, and the fix was a restart nobody knew to do.A server that misses the boot is now retried in the background: after a
minute, then doubling to a two-hour ceiling. Each reconnect registers that
server's tools on the live tool executor, so the fantasy command starts
working mid-process and/aufhocker espnff helpflips from "not connected"
on its own. Both messages now say to wait rather than to restart.Backoff rather than a fixed interval because the two failures underneath
have different lengths: a co-boot race is over inside a minute, while a
server that is genuinely down is down for hours and polling it every minute
buys nothing. Only the servers that are actually missing are retried — a
session that connected is held open as before, since re-handshaking a
working server would drop its tools mid-flight. Shutdown cancels the timer.
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
-
-
v1.20.0
Stablereleased this
2026-09-13 16:17:16 -05:00 | 53 commits to main since this releaseChanged
-
Remade games no longer count toward prediction accuracy. A game that
ends in the first five minutes is a remake: someone failed to connect and
the team voted it dead. Riot still records it as a loss for all ten players,
so every remake previously landed in the accuracy record as a real outcome,
scoring a prediction against a game nobody played.The end-of-game embed now says
🔄 Remakewith the duration and nothing
else: no KDA, no CS/min, no vision, no prediction verdict, no running
record. The prediction row is kept and flaggedremake, which leaves it
visible in the history whileactual_winnerstays NULL, and NULL is what
keeps it out of/aufhocker lol predictionsand the per-game record line.Detection prefers Riot's own
gameEndedInEarlySurrenderflag and falls back
to the five-minute duration threshold when it is absent. A zero duration is
Riot saying "no data", not a zero-second game, so it is never treated as a
remake.The same filter applies to the recent champion W/L shown on the pre-game
embed and fed to the prediction prompt, which was counting remakes as
losses and dragging the record it reported on both.Migration 009 adds the flag and backfills it: predictions already scored
against a sub-five-minute game (identifiable becauselol_active_games
keeps the match result as JSONB and is never pruned) are un-scored, so the
displayed accuracy corrects itself on deploy.
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
-
-
released this
2026-09-10 22:25:44 -05:00 | 54 commits to main since this releaseFixed
-
/aufhocker espnff mcpcan resolve a Discord mention to a team. Asking
"how is @Someone's team doing?" got back "I can't resolve a Discord mention
to an ESPN team on my own" — true, and useless, because the bot had the
mapping and wasn't passing it on.The prompt carried only the asker's own team id. It now carries every mapped
manager as<@id> (Name) manages team_id N, joining the two halves that are
configured separately and meet nowhere else:ESPNFF_TEAM_MAPsupplies the
team id,user-mappings.jsonsupplies the name. A manager with no name entry
is still listed — unnamed and resolvable beats named and absent.Worth knowing why it could not work before: a mention arrives in the query as
raw markup (<@790374074235879454>), not a display name; the fantasy server
knows only ESPN display names; anduser-mappings.jsonfeeds channel
history, which this command deliberately never sends. Nothing in that chain
connected a snowflake to a team.An unmapped id still cannot be placed, and the model is told to ask which
team is meant rather than pick one — a plausible wrong team is the failure
that reads exactly like an answer.
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
-
-
released this
2026-09-10 22:21:01 -05:00 | 55 commits to main since this releaseFixed
-
"Make Public" now removes the whisper it published. Previously the
ephemeral copy stayed on screen, so the same answer appeared twice — and the
stale copy kept a live "Make Public" button on it, inviting a second post of
the same thing. A third ephemeral message ("Response has been made public!")
sat below both; it is gone, because the public message is its own
acknowledgement.A split answer has its ephemeral follow-ups cleared too, not just the message
carrying the button.Deletion is best-effort by necessity: an interaction token lasts 15 minutes
and a pending response lasts an hour, so a late click cannot delete anything.
The fallback collapses the whisper to one line with no button, which is the
part that matters.
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
-
-
released this
2026-09-10 22:16:14 -05:00 | 56 commits to main since this releaseChanged
-
The fantasy tools are no longer offered to
/aufhocker query-chat. They
reach Claude only through the command that names them — today,
/aufhocker espnff mcp.Borrowed tools used to be appended to
ClaudeClient's default set, which
made general chat a second, undocumented way into the league data: no command
asked for it, nothing in Discord said it was happening, and ten
league-specific tools sat in the menu for every unrelated question. The
default set is nowAVAILABLE_TOOLSand nothing else.The executor still executes borrowed tools — it is simply no longer asked
what it holds.ToolExecutor.getDynamicTools()is gone from the interface
ClaudeClientconsumes; advertising is the calling command's job.The boot line now names who gets what:
chatTools=web_search,web_fetch espnffTools=get_league_info,…
CI note: this commit's
build-and-testrun was cancelled when v1.18.1 was pushed on top of it minutes later. Its changes were verified by the full local gate and shipped in the v1.18.1 image, whose CI passed.Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
-