Repository navigation
fix(commands): color tags, encoded queries, missing-key and paging fixes - #207
Merged
Merged
Conversation
- MyInstantsSearch: the "No sounds found" message was a plain string with
doubled braces, so players saw the literal {{darkred}} tags.
- UrbanDictionary / OpenWeather: pass user input through params= so it is
URL-encoded (fixes "a&b", "#", and appid injection). OpenWeather now
checks for a missing API key like WolframAlpha/WUnderground.
- MyInstantsSearch: tolerate a missing "parameters" block and a missing
VoiceServer.Proxy key.
- Disable: drop the unreachable "disabled by a higher level user" branch
(it sat inside `if not disabled`).
- Search / MyInstantsSearch / Help: clamp max_results to >= 1 and stop
shadowing the max builtin; remove the dead first start/end computation
in get_menu_page_content.
Closes #192
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
16 tasks done
WareZ57
approved these changes
Oct 28, 2026
WareZ57
left a comment
There was a problem hiding this comment.
Went through this against #192 item by item, on top of current master (trial merge with git merge-tree):
- Color tag: fixed. The f-string variant on the line above was already right.
!ud/!w:Utils.FetchJsonon master still passesparamsthrough tosession.get, so this still works after the merge. The OpenWeather key check sits in the same place as in WolframAlpha and WUnderground.- MyInstants
KeyErrors: both fixed..get("Proxy") or Nonestill maps""toNone. Disable: the removed check was unreachable with non-negative levels, and!disableis level 3 in the default config anyway. Reachable behaviour is unchanged.- Paging: all three are clamped, the builtin
maxis no longer shadowed, and the code that actually runs inget_menu_page_contentis the same as before.
The only conflict is VERSION: master is at 1.8.39 after the batch, and this branch bumps 1.8.26 -> 1.8.40. Commands.py merges cleanly. Keeping 1.8.40 resolves it. The description still says "No VERSION bump", which hasn't been true since the second commit.
Out of scope and already in the #177 backlog: a level-0 !disable still stores disabled = 0.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Small correctness fixes in
Commands.py. Scope is limited toBaseCommand.get_menu_page_content,UrbanDictionary,OpenWeather,Search,Disable,MyInstantsSearchandHelp.Literal color tags (
MyInstantsSearch)The "No sounds found" message was a plain string with doubled braces, so players saw
{{darkred}}[MyInstants]{{default}}. It now uses single braces{darkred}/{default}, the same tags the f-string messages around it produce.Encoded query strings (
UrbanDictionary,OpenWeather)User text was interpolated straight into the URL.
!ud a&bdroppedb, a#in a city name cut the query, and&appid=...could inject parameters. Both commands now pass their query throughUtils.FetchJson(..., params=...), so aiohttp/yarl URL-encodes it:!ud a&b->.../define?term=a%26b!w São Paulo->...?APPID=KEY&units=metric&q=S%C3%A3o+Paulo!w x#y&appid=evil->...&q=x%23y%26appid%3Devil...&lat=1.5&lon=-2.25(same values as before)OpenWeatheralso checks for a missing API key now, the same wayWolframAlpha/WUndergrounddo: it sends a private "not configured (API key missing)" message and returns1before any request goes out. Previously the player got the raw 401 message from the API.Missing-key crashes (
MyInstantsSearch)command_config["parameters"]raisedKeyErrorwhen the command had noparametersblock. It now usescommand_config.get("parameters", {})once and readssearch_cmd/keywords_banned/max_resultsfrom that.config["VoiceServer"]["Proxy"]raisedKeyErrorwhenProxywas omitted. It now uses.get("Proxy") or None, which matchesFFmpegAudioPlayer. An empty string still maps toNone, as before.Dead check in
DisableThe
disabled > player.admin.levelcheck sat insideif not self.torchlight.disabled. In that branchdisabledis falsy (False/0), and admin levels are never negative, so the check could never be true. I removed it. I did not move it into theelsebranch because that would change behavior: today a second!disablealways answers "Torchlight is already disabled.", whatever the caller's level, and that stays the same. I checked that the reachable paths behave the same as on master for callers of level 0, 3 and 5, both fresh and already disabled.Paging (
Search,MyInstantsSearch,Help,get_menu_page_content)max_resultsis clamped withmax(1, ...). A configured0used to raiseZeroDivisionError, and it now shows one item per page.maxtomax_resultsso it no longer shadows the builtin. That shadowing is also why the clamp could not usemax()before.get_menu_page_contentcomputedstart/endtwice and the first result was always overwritten. I removed the first computation. The effective code is unchanged:start = (page - 1) * max_items; end = start + max_items.Test plan
Torchlight/config/player, monkeypatchedUtils.FetchJsonto capture URL + params):get_menu_page_contentoutput compared with master's (including key order) over 4071 combinations: result sizes 0-24,max_items1-7, pages 0 to max_pages+2, searchNone/""/"foo". All identical.!ud a&b,!w São Paulo,!w x#y&appid=eviland the GeoIP path are shown above.!wwith an emptyOpenWeatherAPIKeysends the private message, returns1and makes no request.MyInstantsSearchwith noparametersblock and noVoiceServer.Proxyno longer raises (proxy=None,search_only=False). "No sounds found" now shows{darkred}[MyInstants]{default} .... With a proxy andsearch_cmd, the proxy andsearch_only=Trueare passed through, and banned keywords are still rejected.Search/Help/MyInstantsSearchwithmax_results: 0build a menu ("Displaying 1-1 of N") and do not raiseZeroDivisionError.Disableoutput, return values and the resultingdisabledvalue match master.ruff check .,ruff format --check .,mypy: no new errors. The only errors left are the 3 known baseline ones on master (UP041 inFFmpegAudioPlayer.py, arg-type inFlareSolverr.py), which CI: Python Linting is red on master since the Python 3.12 bump (ruff UP041, mypy arg-type) #178 handles.No VERSION bump (batch policy, see #177).
Closes #192
Part of #177
🤖 Generated with Claude Code