Skip to content

Honor +Arg=Val and -Arg in ifttt:// URLs - #1831

Merged
caronc merged 2 commits into
caronc:masterfrom
MaxFreedomPollard:fix/ifttt-payload-tokens
Oct 23, 2026
Merged

caronc merged 2 commits into
caronc:masterfrom
MaxFreedomPollard:fix/ifttt-payload-tokens

Conversation

@MaxFreedomPollard

Copy link
Copy Markdown
Contributor

Description

Related issue (if applicable): #533

The IFTTT service page documents ?+Arg=Val to add Arg to the payload and ?-Arg to drop value1, value2 or value3 (for example ifttt://{WebhookID}@{Event}/?+NewArg=ArgValue and ifttt://{WebhookID}@{Event}/?-value3). Neither one does anything:

>>> obj = Apprise.instantiate("ifttt://WebHookID@EventID/?+switch=on&-value1&-value2")
>>> obj.add_tokens, obj.del_tokens
({}, [])

The request body is still {"value1": "title", "value2": "body", "value3": "info"}. The log in #533 shows the same thing: ?+purple=orange is in the URL but not in the IFTTT Payload: line.

Cause: NotifyIFTTT.__init__() takes add_tokens and del_tokens (apprise/plugins/ifttt.py:140), the names template_kwargs declares, but parse_url() returns the parsed +/- arguments as add_token and del_token (apprise/plugins/ifttt.py:355-356). Those land in **kwargs and are ignored.

That hid a second bug. url() builds the + arguments with for k, v in self.add_tokens (apprise/plugins/ifttt.py:321), which unpacks the dict's keys, so it raises ValueError: too many values to unpack (expected 2) whenever add_tokens is set. YAML already fills add_tokens from a +key: value sub-key, and the config loader calls url(), so this entry fails to load today (Could not load Apprise YAML configuration entry #1, item #1):

urls:
  - ifttt://WebHookID@EventID:
     - +switch: 'on'

Fix: parse_url() returns add_tokens and del_tokens, and url() iterates self.add_tokens.items(). Both lines are needed: with only the parse side fixed, every URL with a + argument crashes in url(), including the existing ?+TemplateKey=TemplateVal entry in apprise_url_tests. No documentation change is needed; this makes the documented syntax work.

Checklist

  • Documentation ticket created (if applicable): not applicable, the documented +Arg=Val and -Arg syntax is unchanged
  • The change is tested and works locally.
  • No commented-out code in this PR.
  • No lint errors (use tox -e lint and optionally tox -e format).
  • Test coverage added or updated (use tox -e qa).

Testing

Added test_plugin_ifttt_url_tokens to tests/test_plugin_ifttt.py. It loads ifttt://WebHookID@EventID/?+switch=on&-value1&-value2, checks that the request body is {"value3": "info", "switch": "on"}, then reloads the object from url() and checks that both token sets survive. With only apprise/plugins/ifttt.py reverted it fails with assert {} == {'switch': 'on'}.

With the fix, on Python 3.12 with the dev and all-plugins extras:

  • pytest tests/test_plugin_ifttt.py: 3 passed
  • pytest tests -n 8: 3836 passed, 31 skipped
  • apprise/plugins/ifttt.py coverage: 100% (run together with the delivery tracking and config tests)
  • ruff check . and ruff format --check . on the pinned ruff 0.15.8: pass

Anyone can reproduce without an IFTTT account:

python -c "from apprise import Apprise; o = Apprise.instantiate('ifttt://WebHookID@EventID/?+switch=on&-value1'); print(o.add_tokens, o.del_tokens)"

On master this prints {} []. On this branch it prints {'switch': 'on'} {'value1'}.

🤖 Generated with Claude Code

The ifttt:// documentation describes ?+Arg=Val to add an entry to the
payload and ?-Arg to drop one of value1, value2 or value3. Neither
reaches the plugin. NotifyIFTTT.__init__() takes add_tokens and
del_tokens (apprise/plugins/ifttt.py:140), but parse_url() returns the
parsed +/- arguments as add_token and del_token
(apprise/plugins/ifttt.py:355-356). Nothing accepts those names, so they
are dropped and every notification goes out with the default value1,
value2 and value3 payload.

This hid a second bug in url(): it unpacks self.add_tokens, a dict, as
key/value pairs without .items() (apprise/plugins/ifttt.py:321), so it
raises ValueError as soon as add_tokens is set. A YAML entry using a
"+key: value" sub-key populates add_tokens through the template_kwargs
mapping, which is why such an entry fails to load today.

parse_url() now returns add_tokens and del_tokens, and url() iterates
add_tokens.items(). test_plugin_ifttt_url_tokens checks the payload and
the url() round trip; it fails without this change.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@codecov

codecov Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (2b41a45) to head (832a2e4).
⚠️ Report is 3 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##            master     #1831    +/-   ##
==========================================
  Coverage   100.00%   100.00%            
==========================================
  Files          254       255     +1     
  Lines        41324     41468   +144     
  Branches      7140      7165    +25     
==========================================
+ Hits         41324     41468   +144     
Files with missing lines Coverage Δ
apprise/plugins/ifttt.py 100.00% <100.00%> (ø)

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@caronc
caronc merged commit c6d3af3 into caronc:master Oct 23, 2026
20 checks passed
@caronc

caronc commented Oct 23, 2026

Copy link
Copy Markdown
Owner

Thank you for this PR! 🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants