youpdated 0.2.1__tar.gz → 0.3.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {youpdated-0.2.1 → youpdated-0.3.1}/ADDING_SOURCES.md +21 -0
- {youpdated-0.2.1 → youpdated-0.3.1}/CHANGELOG.md +126 -0
- {youpdated-0.2.1 → youpdated-0.3.1}/PKG-INFO +119 -17
- {youpdated-0.2.1 → youpdated-0.3.1}/README.md +118 -16
- {youpdated-0.2.1 → youpdated-0.3.1}/pyproject.toml +1 -1
- {youpdated-0.2.1 → youpdated-0.3.1}/youpdated/__init__.py +1 -1
- {youpdated-0.2.1 → youpdated-0.3.1}/youpdated/cli.py +118 -10
- {youpdated-0.2.1 → youpdated-0.3.1}/youpdated/config.py +107 -1
- {youpdated-0.2.1 → youpdated-0.3.1}/youpdated/http.py +92 -12
- {youpdated-0.2.1 → youpdated-0.3.1}/youpdated/models.py +11 -0
- {youpdated-0.2.1 → youpdated-0.3.1}/youpdated/render/json_out.py +3 -0
- {youpdated-0.2.1 → youpdated-0.3.1}/youpdated/render/terminal.py +28 -3
- youpdated-0.3.1/youpdated/runner.py +206 -0
- {youpdated-0.2.1 → youpdated-0.3.1}/youpdated/sources/browser.py +4 -2
- {youpdated-0.2.1 → youpdated-0.3.1}/youpdated/sources/feed.py +5 -3
- {youpdated-0.2.1 → youpdated-0.3.1}/youpdated/sources/github.py +23 -1
- {youpdated-0.2.1 → youpdated-0.3.1}/youpdated/sources/itch.py +22 -10
- {youpdated-0.2.1 → youpdated-0.3.1}/youpdated/sources/npm.py +3 -0
- {youpdated-0.2.1 → youpdated-0.3.1}/youpdated/sources/youtube.py +4 -2
- youpdated-0.3.1/youpdated/state.py +359 -0
- {youpdated-0.2.1 → youpdated-0.3.1}/youpdated.egg-info/PKG-INFO +119 -17
- youpdated-0.2.1/youpdated/runner.py +0 -135
- youpdated-0.2.1/youpdated/state.py +0 -203
- {youpdated-0.2.1 → youpdated-0.3.1}/CONTRIBUTING.md +0 -0
- {youpdated-0.2.1 → youpdated-0.3.1}/LICENSE +0 -0
- {youpdated-0.2.1 → youpdated-0.3.1}/MANIFEST.in +0 -0
- {youpdated-0.2.1 → youpdated-0.3.1}/SECURITY.md +0 -0
- {youpdated-0.2.1 → youpdated-0.3.1}/setup.cfg +0 -0
- {youpdated-0.2.1 → youpdated-0.3.1}/youpdated/__main__.py +0 -0
- {youpdated-0.2.1 → youpdated-0.3.1}/youpdated/cleanup.py +0 -0
- {youpdated-0.2.1 → youpdated-0.3.1}/youpdated/crypto.py +0 -0
- {youpdated-0.2.1 → youpdated-0.3.1}/youpdated/py.typed +0 -0
- {youpdated-0.2.1 → youpdated-0.3.1}/youpdated/registry.py +0 -0
- {youpdated-0.2.1 → youpdated-0.3.1}/youpdated/render/__init__.py +0 -0
- {youpdated-0.2.1 → youpdated-0.3.1}/youpdated/render/rss_out.py +0 -0
- {youpdated-0.2.1 → youpdated-0.3.1}/youpdated/sources/__init__.py +0 -0
- {youpdated-0.2.1 → youpdated-0.3.1}/youpdated/sources/base.py +0 -0
- {youpdated-0.2.1 → youpdated-0.3.1}/youpdated/sources/generic.py +0 -0
- {youpdated-0.2.1 → youpdated-0.3.1}/youpdated/sources/steam.py +0 -0
- {youpdated-0.2.1 → youpdated-0.3.1}/youpdated.egg-info/SOURCES.txt +0 -0
- {youpdated-0.2.1 → youpdated-0.3.1}/youpdated.egg-info/dependency_links.txt +0 -0
- {youpdated-0.2.1 → youpdated-0.3.1}/youpdated.egg-info/entry_points.txt +0 -0
- {youpdated-0.2.1 → youpdated-0.3.1}/youpdated.egg-info/requires.txt +0 -0
- {youpdated-0.2.1 → youpdated-0.3.1}/youpdated.egg-info/top_level.txt +0 -0
|
@@ -216,6 +216,26 @@ uid=str(index) # broken: shifts as items are added
|
|
|
216
216
|
|
|
217
217
|
When an upstream gives you no id at all, fingerprint the content: hash the fields that define the item. [itch.py](youpdated/sources/itch.py) does this for game builds: filenames, sizes, and the update timestamp hash into one uid.
|
|
218
218
|
|
|
219
|
+
### Tags are what users filter on
|
|
220
|
+
|
|
221
|
+
`tags`: a user's `ignore:` rules match against them, so a type
|
|
222
|
+
untagged is not able to be hidden. Tag each update with what it *is*,
|
|
223
|
+
using the vocabulary already in use where it fits: `release`, `prerelease`,
|
|
224
|
+
`tag`, `commit`, `latest`, `devlog`, `news`, `video`, `item`, and add your own
|
|
225
|
+
where needed.
|
|
226
|
+
|
|
227
|
+
```python
|
|
228
|
+
tags=("release",) + (("prerelease",) if item["draft_or_rc"] else ())
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
Tags are additive, and an update is dropped if **any** of its tags is ignored.
|
|
232
|
+
So describing an item from several angles at once is the point: tagging a
|
|
233
|
+
release candidate `("release", "prerelease")` lets one user ignore every
|
|
234
|
+
release and another ignore only the candidates.
|
|
235
|
+
|
|
236
|
+
You do not need to handle `ignore` yourself. It is lifted off the config entry
|
|
237
|
+
before `targets()` ever sees it, and applied to whatever you return.
|
|
238
|
+
|
|
219
239
|
### Filling in a label during fetch
|
|
220
240
|
|
|
221
241
|
Sometimes the friendly name is only available from the response. Assign it to `target.label`; the renderers pick it up:
|
|
@@ -329,5 +349,6 @@ Users then configure it like any built-in source. A plugin that fails to import
|
|
|
329
349
|
- [ ] Expected non-200s handled with `soft_statuses`; real failures left to raise
|
|
330
350
|
- [ ] Returns `[]` rather than inventing an update
|
|
331
351
|
- [ ] `published` is timezone-aware UTC (or `None`)
|
|
352
|
+
- [ ] `tags` describe the update type, so `ignore:` rules can match them
|
|
332
353
|
- [ ] Tests cover parsing, both config shapes, and uid stability
|
|
333
354
|
- [ ] Registered — `@register` plus an import, or an entry point
|
|
@@ -4,6 +4,130 @@ All notable changes to this project are documented here. The format follows
|
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to
|
|
5
5
|
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [0.3.1] — 2026-10-10
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **itch builds no longer re-report on unchanged pages.** itch.io shuffles HTML
|
|
12
|
+
attribute order, and the upload list was only read in one
|
|
13
|
+
order, so some fetches saw no files and fingerprinted a "new build". Successive
|
|
14
|
+
runs each reported a different handful of games until every variant had been
|
|
15
|
+
seen. Upload and timestamp parsing no longer depend on attribute order.
|
|
16
|
+
- **YouTube Shorts no longer re-report when the feed falls back.** The official
|
|
17
|
+
feed links Shorts as `/shorts/<id>`, which was not recognised, so Shorts were
|
|
18
|
+
recorded as `yt:video:yt:video:<id>` there and `yt:video:<id>` through Invidious
|
|
19
|
+
or Data API. Each switch reported Shorts again. Existing
|
|
20
|
+
history is migrated on first open, so nothing already seen comes back.
|
|
21
|
+
- **`--no-save` really leaves the state alone.** It still stored each feed's
|
|
22
|
+
ETag/Last-Modified, so the next real run was answered 304 and silently skipped
|
|
23
|
+
whatever the preview had shown. (Whoops)
|
|
24
|
+
- **A target that fails partway no longer hides its new items.** If one of a
|
|
25
|
+
target's fetches failed (e.g. GitHub `watch: [releases, commits]` with commits
|
|
26
|
+
down), the others' validators were still stored while their items were
|
|
27
|
+
discarded, so the next run got a 304 and never reported them. Validators are
|
|
28
|
+
now stored only alongside the items they cover.
|
|
29
|
+
- **Feeds listed oldest-first report new entries.** Entries were cut to the
|
|
30
|
+
limit in document order before sorting, so on an oldest-first feed longer than
|
|
31
|
+
the limit the newest posts never made it in. Affects `feed`, Steam, itch
|
|
32
|
+
devlogs, and GitHub atom feeds.
|
|
33
|
+
- **Chrome no longer errors** when a version is first listed without a rollout
|
|
34
|
+
start time and later with.
|
|
35
|
+
- **Removing an `ignore:` rule shows what it hid.** Ignored items
|
|
36
|
+
are not recorded, but the feed's validators were, so hidden items stayed hidden until it next changed.
|
|
37
|
+
Each target's rules are now recorded, and a target whose rules changed is fetched fully once.
|
|
38
|
+
Every target is fetched in full once after upgrading.
|
|
39
|
+
|
|
40
|
+
## [0.3.0] — 2026-10-07
|
|
41
|
+
|
|
42
|
+
### Added
|
|
43
|
+
|
|
44
|
+
- **`ignore:` rules drop update types** (#11). Every update already
|
|
45
|
+
carried tags describing what it is; those are now filterable. A bare list
|
|
46
|
+
applies everywhere, a mapping narrows it to one source (`'*'` for all), and a per-entry
|
|
47
|
+
`ignore:` adds to whichever applies:
|
|
48
|
+
|
|
49
|
+
```yaml
|
|
50
|
+
ignore:
|
|
51
|
+
'*': [prerelease]
|
|
52
|
+
github: [commit]
|
|
53
|
+
|
|
54
|
+
sources:
|
|
55
|
+
github:
|
|
56
|
+
- repo: astral-sh/uv
|
|
57
|
+
ignore: [tag] # global rules + `tag`
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
An update is dropped if it carries any listed tag. Ignored items are not
|
|
61
|
+
recorded as seen, so removing a rule later shows what it was hiding.
|
|
62
|
+
The run summary and `--json` both count what was dropped.
|
|
63
|
+
See [Ignoring update types](README.md#ignoring-update-types) for the tag vocabulary per source.
|
|
64
|
+
|
|
65
|
+
- **GitHub prereleases are tagged without a token.** `prerelease` previously came only from the
|
|
66
|
+
REST API, which needs `GITHUB_TOKEN`, so on the anonymous `.atom` path nothing was tagged.
|
|
67
|
+
It is now inferred from the tag name (`v3.15.0rc2`, `1.2.0-beta.1`, `0.12.0-alpha`), and a
|
|
68
|
+
token takes precedence. Platform and build suffixes (`v1.0.0-linux`, `v4.2.0+build.7`)
|
|
69
|
+
are untouched.
|
|
70
|
+
|
|
71
|
+
- **npm prereleases are tagged.** Any semver version with a prerelease suffix now carries
|
|
72
|
+
`prerelease`. Build metadata (`+build-7`) does not count, even with a hyphen in it.
|
|
73
|
+
|
|
74
|
+
- **Runs report progress instead of going quiet.** A check printed nothing until the last target
|
|
75
|
+
landed, so a slow source was indistinguishable from a hang. Interactive runs now show a live
|
|
76
|
+
line naming the targets still in flight, with a count and elapsed time. It is suppressed under
|
|
77
|
+
`-v`, `--test`, and when output is not a terminal.
|
|
78
|
+
|
|
79
|
+
- **A desktop example app** (#13), in `examples/desktop/`. A simple window checks on a schedule,
|
|
80
|
+
sends a notification, and lists what changed.
|
|
81
|
+
Uses standard library and youpdated. It reads the same config and
|
|
82
|
+
history as the CLI, and prompts for a passphrase when either is encrypted.
|
|
83
|
+
Its own CI covers Linux, macOS, and Windows, and runs only when `examples/` changes
|
|
84
|
+
|
|
85
|
+
### Changed
|
|
86
|
+
|
|
87
|
+
- **Install docs now with `pipx install youpdated`.** The package has been on PyPI since 0.1.0,
|
|
88
|
+
but the README still told people to clone the repo and install from the working tree.
|
|
89
|
+
Installing from source is now a subsection.
|
|
90
|
+
The scheduling examples point at a `pipx` path rather than a repo virtualenv.
|
|
91
|
+
- **itch builds are tagged `build`, and page-only changes `page`,** instead of both being
|
|
92
|
+
`release`. The tags say what changed, so `ignore:` can tell them apart. Anything filtering
|
|
93
|
+
`--json` or `--rss` output on `release` for itch should use `build`.
|
|
94
|
+
|
|
95
|
+
### Fixed
|
|
96
|
+
|
|
97
|
+
- **A host's pacing lock is no longer held across its own wait.** `_pace` slept while holding the
|
|
98
|
+
per-host lock, so every other thread bound for that host blocked in `acquire` for the whole
|
|
99
|
+
gap, with no way to be interrupted, and a thread waiting its turn could be scheduled
|
|
100
|
+
ahead of one ready to do real work. Each caller now reserves a slot under the lock and waits
|
|
101
|
+
outside it. The spacing between requests to one host is unchanged.
|
|
102
|
+
- **Progress bar moved around** (#14). The target names led the line, so the bar
|
|
103
|
+
and counter shifted sideways every time they changed, and a long name squeezed the bar out.
|
|
104
|
+
The spinner, bar, count, elapsed time and failure count now come first at a fixed
|
|
105
|
+
width, and the names fill what is left of the line, truncated with an ellipsis. Names are
|
|
106
|
+
shown literally, so one containing brackets (`[/x]`) no longer crashes the bar.
|
|
107
|
+
- **Rate-limit retries honor `Retry-After`** (#17). A 429 or 503 was retried on a fixed
|
|
108
|
+
rate ignoring any potential 'Retry-After' sent. The wait now follows the header (seconds or an HTTP-date)
|
|
109
|
+
and holds the whole host, so other targets on that site wait too.
|
|
110
|
+
A server asking for more than 60s fails that request at once instead of stalling the run.
|
|
111
|
+
Without the header, the fixed backoff applies as before.
|
|
112
|
+
- **The history database is pruned** (#18). Seen items were added, so the
|
|
113
|
+
database grew, including for targets removed from the config, and with
|
|
114
|
+
encryption, the whole thing is decrypted and re-encrypted each run. An item missing from
|
|
115
|
+
every fetch for longer than the new top-level `expiry:` (default `1y`, `never` to keep
|
|
116
|
+
everything) is now forgotten, and the file is compacted. Items still listed by their source are
|
|
117
|
+
never pruned, and stored validators older than half the expiry are skipped once to
|
|
118
|
+
force a full fetch. Targets that failed or were left out with `--source` keep their history.
|
|
119
|
+
A removed target's baseline expires with its history, so re-adding it later records a new
|
|
120
|
+
baseline instead of reporting everything it has.
|
|
121
|
+
`--json` counts what was pruned, and `--since` now also accepts years (`1y`).
|
|
122
|
+
- **A target added later no longer dumps a backlog.** The first run baseline applied to the
|
|
123
|
+
whole state, so after it, a newly added target reported every item it had as new. Same
|
|
124
|
+
for a target that failed the first run, or `-s`. Baselines are now
|
|
125
|
+
recorded per target on its first successful fetch, and the run names those targets. State
|
|
126
|
+
from earlier versions is read as already baselined, so nothing is swallowed on upgrade.
|
|
127
|
+
A target's first fetch sends no stored validators, so a new channel on a document another
|
|
128
|
+
target already watches (Brave, Firefox, Edge) records a real baseline instead of a 304.
|
|
129
|
+
- **`--test` lines read `[test] GET`**, not `[test]] GET`.
|
|
130
|
+
|
|
7
131
|
## [0.2.1] — 2026-08-25
|
|
8
132
|
|
|
9
133
|
### Fixed
|
|
@@ -146,6 +270,8 @@ First release.
|
|
|
146
270
|
- Firefox publishes current versions, so it reports one item per channel.
|
|
147
271
|
- Edge exposes release notes only for the stable and beta channels. (But like, it's Edge, why do you want to know when it updates?)
|
|
148
272
|
|
|
273
|
+
[0.3.1]: https://github.com/Void1-1/youpdated/releases/tag/v0.3.1
|
|
274
|
+
[0.3.0]: https://github.com/Void1-1/youpdated/releases/tag/v0.3.0
|
|
149
275
|
[0.2.1]: https://github.com/Void1-1/youpdated/releases/tag/v0.2.1
|
|
150
276
|
[0.2.0]: https://github.com/Void1-1/youpdated/releases/tag/v0.2.0
|
|
151
277
|
[0.1.1]: https://github.com/Void1-1/youpdated/releases/tag/v0.1.1
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: youpdated
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: Simple update tracker for games, apps, and packages
|
|
5
5
|
Author-email: Void1-1 <161782542+Void1-1@users.noreply.github.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -84,7 +84,35 @@ Requires **Python 3.11 or newer** (`python3 --version` to check). CI runs the fu
|
|
|
84
84
|
**Linux, macOS, and Windows** across Python 3.11–3.14.
|
|
85
85
|
|
|
86
86
|
```sh
|
|
87
|
-
|
|
87
|
+
pipx install youpdated
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
[pipx](https://pipx.pypa.io) puts the `youpdated` command on your `PATH` in its own isolated
|
|
91
|
+
environment. Plain `pip` works too, but it installs into whatever environment is active:
|
|
92
|
+
|
|
93
|
+
```sh
|
|
94
|
+
pip install youpdated
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Add encryption support (see [Encryption at rest](#encryption-at-rest)) with either installer:
|
|
98
|
+
|
|
99
|
+
```sh
|
|
100
|
+
pipx install 'youpdated[encryption]'
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Verify:
|
|
104
|
+
|
|
105
|
+
```sh
|
|
106
|
+
youpdated --version # -> youpdated 0.2.1
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### From source
|
|
110
|
+
|
|
111
|
+
To run an unreleased version or work on the tool itself:
|
|
112
|
+
|
|
113
|
+
```sh
|
|
114
|
+
git clone https://github.com/Void1-1/youpdated
|
|
115
|
+
cd youpdated
|
|
88
116
|
python3 -m venv .venv
|
|
89
117
|
.venv/bin/pip install .
|
|
90
118
|
```
|
|
@@ -96,24 +124,17 @@ python -m venv .venv
|
|
|
96
124
|
.venv\Scripts\pip install .
|
|
97
125
|
```
|
|
98
126
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
it on your `PATH`:
|
|
127
|
+
Puts the command at `.venv/bin/youpdated` on macOS/Linux and `.venv\Scripts\youpdated.exe` on
|
|
128
|
+
Windows. Call it by that full path, or put the directory on your `PATH`:
|
|
102
129
|
|
|
103
130
|
```sh
|
|
104
131
|
export PATH="$PWD/.venv/bin:$PATH" # macOS / Linux
|
|
105
|
-
youpdated --version # -> youpdated 0.2.0
|
|
106
132
|
```
|
|
107
133
|
|
|
108
134
|
```powershell
|
|
109
135
|
$env:PATH = "$PWD\.venv\Scripts;$env:PATH" # Windows
|
|
110
|
-
youpdated --version
|
|
111
136
|
```
|
|
112
137
|
|
|
113
|
-
To make that permanent, add the `export` line to your `~/.zshrc`, or the `$env:PATH` line to your
|
|
114
|
-
PowerShell profile. Examples assume `youpdated` is on your `PATH`; if it isn't, substitute the full
|
|
115
|
-
path above.
|
|
116
|
-
|
|
117
138
|
## 2. Create your config
|
|
118
139
|
|
|
119
140
|
```sh
|
|
@@ -172,12 +193,19 @@ privacy:
|
|
|
172
193
|
concurrency: 4
|
|
173
194
|
timeout: 20
|
|
174
195
|
|
|
196
|
+
ignore: # update types you never want reported
|
|
197
|
+
'*': [prerelease] # '*' is every source
|
|
198
|
+
github: [commit]
|
|
199
|
+
|
|
200
|
+
expiry: 1y # forget items missing from every fetch this long
|
|
201
|
+
|
|
175
202
|
sources:
|
|
176
203
|
github:
|
|
177
204
|
- python/cpython # easy
|
|
178
205
|
- repo: astral-sh/uv # advanced:
|
|
179
206
|
watch: [releases, commits] # releases | tags | commits
|
|
180
207
|
branch: main # for `commits`
|
|
208
|
+
ignore: [tag] # adds to the rules above, this entry only
|
|
181
209
|
|
|
182
210
|
npm:
|
|
183
211
|
- express
|
|
@@ -214,6 +242,73 @@ sources:
|
|
|
214
242
|
limit: 5
|
|
215
243
|
```
|
|
216
244
|
|
|
245
|
+
### Ignoring update types
|
|
246
|
+
|
|
247
|
+
Every update carries one or more **tags** describing what it is. An `ignore:`
|
|
248
|
+
rule drops any update carrying a tag you list.
|
|
249
|
+
|
|
250
|
+
```yaml
|
|
251
|
+
ignore: [prerelease] # shorthand: applies to every source
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
```yaml
|
|
255
|
+
ignore:
|
|
256
|
+
'*': [prerelease] # every source
|
|
257
|
+
github: [commit, tag] # just this source
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
Either form can be combined with a per-entry rule, which **adds** to it:
|
|
261
|
+
|
|
262
|
+
```yaml
|
|
263
|
+
sources:
|
|
264
|
+
github:
|
|
265
|
+
- python/cpython # global rules only
|
|
266
|
+
- repo: astral-sh/uv
|
|
267
|
+
ignore: [tag] # global rules + `tag`
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
These are the tags each source sets:
|
|
271
|
+
|
|
272
|
+
| Source | Tags |
|
|
273
|
+
| --- | --- |
|
|
274
|
+
| `github` | `release`, `prerelease`, `tag`, `commit` |
|
|
275
|
+
| `npm` | `release`, `prerelease`, `latest` |
|
|
276
|
+
| `itch` | `devlog`, `build`, `page` |
|
|
277
|
+
| `browser` | `release`, plus the channel (`stable`, `beta`, `dev`, `canary`, `esr`, `nightly`) |
|
|
278
|
+
| `youtube` | `video` |
|
|
279
|
+
| `steam` | `news` |
|
|
280
|
+
| `feed` | `item` |
|
|
281
|
+
|
|
282
|
+
An update is dropped if it carries **any** tag listed. A GitHub release
|
|
283
|
+
candidate is tagged both `release` and `prerelease`, so ignoring `prerelease`
|
|
284
|
+
drops it while ordinary releases stay.
|
|
285
|
+
|
|
286
|
+
An itch build is tagged `build`, not `release`. It is a fingerprint of the
|
|
287
|
+
game page, not a published release. A page whose date moved with no new
|
|
288
|
+
files is tagged `page`. So `ignore: [build]` drops new builds while keeping
|
|
289
|
+
devlog posts, and ignoring `release` everywhere leaves itch alone.
|
|
290
|
+
(`watch: [devlog]` on an itch entry still turns builds off outright)
|
|
291
|
+
|
|
292
|
+
Without a `GITHUB_TOKEN`, `prerelease` is inferred from the tag name
|
|
293
|
+
(`v3.15.0rc2`, `1.2.0-beta.1`), since the anonymous `.atom` feeds carry no
|
|
294
|
+
prerelease flag. With a token set, GitHub's own flag is used instead.
|
|
295
|
+
|
|
296
|
+
### How long history is kept
|
|
297
|
+
|
|
298
|
+
The history database remembers every item it has reported so nothing shows up again.
|
|
299
|
+
To bound its growth, an item that hasn't appeared in any fetch for a year is
|
|
300
|
+
forgotten, along with everything from targets you've removed from the config. Change the
|
|
301
|
+
window with `expiry:`, or turn pruning off:
|
|
302
|
+
|
|
303
|
+
```yaml
|
|
304
|
+
expiry: 180d # 30d, 52w, 2y, ... (at least 1d)
|
|
305
|
+
# expiry: never # keep everything
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
Pruning is safe: an item still listed by its source is never forgotten, however old,
|
|
309
|
+
so nothing is reported a second time. Targets that failed this run, or were left out
|
|
310
|
+
with `--source`, keep their history until they next fetch cleanly.
|
|
311
|
+
|
|
217
312
|
Check your config without sending a request:
|
|
218
313
|
|
|
219
314
|
```sh
|
|
@@ -246,6 +341,12 @@ youpdated check --all
|
|
|
246
341
|
|
|
247
342
|
From then on, `youpdated check` prints only what changed since the previous run.
|
|
248
343
|
|
|
344
|
+
The same goes for a target you add later. Its first check records a baseline for that target, and the rest of the run reports as usual:
|
|
345
|
+
|
|
346
|
+
```text
|
|
347
|
+
Baseline recorded for 1 new target(s): npm:react. Their existing items were not reported.
|
|
348
|
+
```
|
|
349
|
+
|
|
249
350
|
---
|
|
250
351
|
|
|
251
352
|
## Command reference
|
|
@@ -253,7 +354,7 @@ From then on, `youpdated check` prints only what changed since the previous run.
|
|
|
253
354
|
```sh
|
|
254
355
|
youpdated check # what's new since last run (the default command)
|
|
255
356
|
youpdated check --all # everything currently published, ignoring history
|
|
256
|
-
youpdated check --since 7d # only items from the last week (30m, 12h, 7d, 2w)
|
|
357
|
+
youpdated check --since 7d # only items from the last week (30m, 12h, 7d, 2w, 1y)
|
|
257
358
|
youpdated check -s github -s npm # limit to some sources
|
|
258
359
|
youpdated check --json # machine-readable output
|
|
259
360
|
youpdated check --rss ~/feeds/you.xml # aggregated Atom feed for a reader
|
|
@@ -282,18 +383,18 @@ Exit codes: `0` success, `1` config, encryption, or proxy error, `2` with `--fai
|
|
|
282
383
|
|
|
283
384
|
## Running it on schedule
|
|
284
385
|
|
|
285
|
-
Once a day is plenty, most of these sources change slowly, and conditional requests make repeat runs cheap. Use absolute paths, since cron and launchd don't inherit your shell's `PATH
|
|
386
|
+
Once a day is plenty, most of these sources change slowly, and conditional requests make repeat runs cheap. Use absolute paths, since cron and launchd don't inherit your shell's `PATH`; `which youpdated` prints yours.
|
|
286
387
|
|
|
287
388
|
**cron** (`crontab -e`) run at 9am and append to a log:
|
|
288
389
|
|
|
289
390
|
```cron
|
|
290
|
-
0 9 * * * /
|
|
391
|
+
0 9 * * * /home/you/.local/bin/youpdated check >> ~/youpdated.log 2>&1
|
|
291
392
|
```
|
|
292
393
|
|
|
293
394
|
**Keep an RSS feed fresh** for a reader to poll. Note that `--rss` writes that run's items, so a plain `check --rss` leaves almost an empty file. For a feed that always holds a rolling window, ask for it. `--no-save` keeps this from interfering with your daily incremental run:
|
|
294
395
|
|
|
295
396
|
```cron
|
|
296
|
-
0 * * * * /
|
|
397
|
+
0 * * * * /home/you/.local/bin/youpdated check --all --since 30d --no-save --rss ~/feeds/youpdated.xml
|
|
297
398
|
```
|
|
298
399
|
|
|
299
400
|
**macOS launchd**: save as `~/Library/LaunchAgents/com.youpdated.check.plist`, then `launchctl load ~/Library/LaunchAgents/com.youpdated.check.plist`:
|
|
@@ -304,7 +405,7 @@ Once a day is plenty, most of these sources change slowly, and conditional reque
|
|
|
304
405
|
<key>Label</key><string>com.youpdated.check</string>
|
|
305
406
|
<key>ProgramArguments</key>
|
|
306
407
|
<array>
|
|
307
|
-
<string>/
|
|
408
|
+
<string>/Users/you/.local/bin/youpdated</string>
|
|
308
409
|
<string>check</string>
|
|
309
410
|
<string>--rss</string>
|
|
310
411
|
<string>/Users/you/feeds/youpdated.xml</string>
|
|
@@ -320,7 +421,8 @@ Once a day is plenty, most of these sources change slowly, and conditional reque
|
|
|
320
421
|
| Symptom | Cause and fix |
|
|
321
422
|
| --- | --- |
|
|
322
423
|
| `Config error: no config file found` | Run `youpdated init`, or pass `--config PATH`. |
|
|
323
|
-
| First run printed nothing | Working as intended
|
|
424
|
+
| First run printed nothing | Working as intended: it recorded a baseline. Run `youpdated check --all` to see current items. |
|
|
425
|
+
| A newly added target printed nothing | Same as above, for that one target. `youpdated check --all -s <source>` shows its current items. |
|
|
324
426
|
| `--all` shows fewer items than expected | Nothing is wrong; sources cap how much history they expose (10–20 items each). |
|
|
325
427
|
| A source appears in the yellow `problems` panel | That one source failed; the rest of the run still completed. Re-run with `-v` to see the request and status. |
|
|
326
428
|
| `unknown source 'X'` | Check spelling against `youpdated sources`. |
|
|
@@ -39,7 +39,35 @@ Requires **Python 3.11 or newer** (`python3 --version` to check). CI runs the fu
|
|
|
39
39
|
**Linux, macOS, and Windows** across Python 3.11–3.14.
|
|
40
40
|
|
|
41
41
|
```sh
|
|
42
|
-
|
|
42
|
+
pipx install youpdated
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
[pipx](https://pipx.pypa.io) puts the `youpdated` command on your `PATH` in its own isolated
|
|
46
|
+
environment. Plain `pip` works too, but it installs into whatever environment is active:
|
|
47
|
+
|
|
48
|
+
```sh
|
|
49
|
+
pip install youpdated
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Add encryption support (see [Encryption at rest](#encryption-at-rest)) with either installer:
|
|
53
|
+
|
|
54
|
+
```sh
|
|
55
|
+
pipx install 'youpdated[encryption]'
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Verify:
|
|
59
|
+
|
|
60
|
+
```sh
|
|
61
|
+
youpdated --version # -> youpdated 0.2.1
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### From source
|
|
65
|
+
|
|
66
|
+
To run an unreleased version or work on the tool itself:
|
|
67
|
+
|
|
68
|
+
```sh
|
|
69
|
+
git clone https://github.com/Void1-1/youpdated
|
|
70
|
+
cd youpdated
|
|
43
71
|
python3 -m venv .venv
|
|
44
72
|
.venv/bin/pip install .
|
|
45
73
|
```
|
|
@@ -51,24 +79,17 @@ python -m venv .venv
|
|
|
51
79
|
.venv\Scripts\pip install .
|
|
52
80
|
```
|
|
53
81
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
it on your `PATH`:
|
|
82
|
+
Puts the command at `.venv/bin/youpdated` on macOS/Linux and `.venv\Scripts\youpdated.exe` on
|
|
83
|
+
Windows. Call it by that full path, or put the directory on your `PATH`:
|
|
57
84
|
|
|
58
85
|
```sh
|
|
59
86
|
export PATH="$PWD/.venv/bin:$PATH" # macOS / Linux
|
|
60
|
-
youpdated --version # -> youpdated 0.2.0
|
|
61
87
|
```
|
|
62
88
|
|
|
63
89
|
```powershell
|
|
64
90
|
$env:PATH = "$PWD\.venv\Scripts;$env:PATH" # Windows
|
|
65
|
-
youpdated --version
|
|
66
91
|
```
|
|
67
92
|
|
|
68
|
-
To make that permanent, add the `export` line to your `~/.zshrc`, or the `$env:PATH` line to your
|
|
69
|
-
PowerShell profile. Examples assume `youpdated` is on your `PATH`; if it isn't, substitute the full
|
|
70
|
-
path above.
|
|
71
|
-
|
|
72
93
|
## 2. Create your config
|
|
73
94
|
|
|
74
95
|
```sh
|
|
@@ -127,12 +148,19 @@ privacy:
|
|
|
127
148
|
concurrency: 4
|
|
128
149
|
timeout: 20
|
|
129
150
|
|
|
151
|
+
ignore: # update types you never want reported
|
|
152
|
+
'*': [prerelease] # '*' is every source
|
|
153
|
+
github: [commit]
|
|
154
|
+
|
|
155
|
+
expiry: 1y # forget items missing from every fetch this long
|
|
156
|
+
|
|
130
157
|
sources:
|
|
131
158
|
github:
|
|
132
159
|
- python/cpython # easy
|
|
133
160
|
- repo: astral-sh/uv # advanced:
|
|
134
161
|
watch: [releases, commits] # releases | tags | commits
|
|
135
162
|
branch: main # for `commits`
|
|
163
|
+
ignore: [tag] # adds to the rules above, this entry only
|
|
136
164
|
|
|
137
165
|
npm:
|
|
138
166
|
- express
|
|
@@ -169,6 +197,73 @@ sources:
|
|
|
169
197
|
limit: 5
|
|
170
198
|
```
|
|
171
199
|
|
|
200
|
+
### Ignoring update types
|
|
201
|
+
|
|
202
|
+
Every update carries one or more **tags** describing what it is. An `ignore:`
|
|
203
|
+
rule drops any update carrying a tag you list.
|
|
204
|
+
|
|
205
|
+
```yaml
|
|
206
|
+
ignore: [prerelease] # shorthand: applies to every source
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
```yaml
|
|
210
|
+
ignore:
|
|
211
|
+
'*': [prerelease] # every source
|
|
212
|
+
github: [commit, tag] # just this source
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Either form can be combined with a per-entry rule, which **adds** to it:
|
|
216
|
+
|
|
217
|
+
```yaml
|
|
218
|
+
sources:
|
|
219
|
+
github:
|
|
220
|
+
- python/cpython # global rules only
|
|
221
|
+
- repo: astral-sh/uv
|
|
222
|
+
ignore: [tag] # global rules + `tag`
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
These are the tags each source sets:
|
|
226
|
+
|
|
227
|
+
| Source | Tags |
|
|
228
|
+
| --- | --- |
|
|
229
|
+
| `github` | `release`, `prerelease`, `tag`, `commit` |
|
|
230
|
+
| `npm` | `release`, `prerelease`, `latest` |
|
|
231
|
+
| `itch` | `devlog`, `build`, `page` |
|
|
232
|
+
| `browser` | `release`, plus the channel (`stable`, `beta`, `dev`, `canary`, `esr`, `nightly`) |
|
|
233
|
+
| `youtube` | `video` |
|
|
234
|
+
| `steam` | `news` |
|
|
235
|
+
| `feed` | `item` |
|
|
236
|
+
|
|
237
|
+
An update is dropped if it carries **any** tag listed. A GitHub release
|
|
238
|
+
candidate is tagged both `release` and `prerelease`, so ignoring `prerelease`
|
|
239
|
+
drops it while ordinary releases stay.
|
|
240
|
+
|
|
241
|
+
An itch build is tagged `build`, not `release`. It is a fingerprint of the
|
|
242
|
+
game page, not a published release. A page whose date moved with no new
|
|
243
|
+
files is tagged `page`. So `ignore: [build]` drops new builds while keeping
|
|
244
|
+
devlog posts, and ignoring `release` everywhere leaves itch alone.
|
|
245
|
+
(`watch: [devlog]` on an itch entry still turns builds off outright)
|
|
246
|
+
|
|
247
|
+
Without a `GITHUB_TOKEN`, `prerelease` is inferred from the tag name
|
|
248
|
+
(`v3.15.0rc2`, `1.2.0-beta.1`), since the anonymous `.atom` feeds carry no
|
|
249
|
+
prerelease flag. With a token set, GitHub's own flag is used instead.
|
|
250
|
+
|
|
251
|
+
### How long history is kept
|
|
252
|
+
|
|
253
|
+
The history database remembers every item it has reported so nothing shows up again.
|
|
254
|
+
To bound its growth, an item that hasn't appeared in any fetch for a year is
|
|
255
|
+
forgotten, along with everything from targets you've removed from the config. Change the
|
|
256
|
+
window with `expiry:`, or turn pruning off:
|
|
257
|
+
|
|
258
|
+
```yaml
|
|
259
|
+
expiry: 180d # 30d, 52w, 2y, ... (at least 1d)
|
|
260
|
+
# expiry: never # keep everything
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
Pruning is safe: an item still listed by its source is never forgotten, however old,
|
|
264
|
+
so nothing is reported a second time. Targets that failed this run, or were left out
|
|
265
|
+
with `--source`, keep their history until they next fetch cleanly.
|
|
266
|
+
|
|
172
267
|
Check your config without sending a request:
|
|
173
268
|
|
|
174
269
|
```sh
|
|
@@ -201,6 +296,12 @@ youpdated check --all
|
|
|
201
296
|
|
|
202
297
|
From then on, `youpdated check` prints only what changed since the previous run.
|
|
203
298
|
|
|
299
|
+
The same goes for a target you add later. Its first check records a baseline for that target, and the rest of the run reports as usual:
|
|
300
|
+
|
|
301
|
+
```text
|
|
302
|
+
Baseline recorded for 1 new target(s): npm:react. Their existing items were not reported.
|
|
303
|
+
```
|
|
304
|
+
|
|
204
305
|
---
|
|
205
306
|
|
|
206
307
|
## Command reference
|
|
@@ -208,7 +309,7 @@ From then on, `youpdated check` prints only what changed since the previous run.
|
|
|
208
309
|
```sh
|
|
209
310
|
youpdated check # what's new since last run (the default command)
|
|
210
311
|
youpdated check --all # everything currently published, ignoring history
|
|
211
|
-
youpdated check --since 7d # only items from the last week (30m, 12h, 7d, 2w)
|
|
312
|
+
youpdated check --since 7d # only items from the last week (30m, 12h, 7d, 2w, 1y)
|
|
212
313
|
youpdated check -s github -s npm # limit to some sources
|
|
213
314
|
youpdated check --json # machine-readable output
|
|
214
315
|
youpdated check --rss ~/feeds/you.xml # aggregated Atom feed for a reader
|
|
@@ -237,18 +338,18 @@ Exit codes: `0` success, `1` config, encryption, or proxy error, `2` with `--fai
|
|
|
237
338
|
|
|
238
339
|
## Running it on schedule
|
|
239
340
|
|
|
240
|
-
Once a day is plenty, most of these sources change slowly, and conditional requests make repeat runs cheap. Use absolute paths, since cron and launchd don't inherit your shell's `PATH
|
|
341
|
+
Once a day is plenty, most of these sources change slowly, and conditional requests make repeat runs cheap. Use absolute paths, since cron and launchd don't inherit your shell's `PATH`; `which youpdated` prints yours.
|
|
241
342
|
|
|
242
343
|
**cron** (`crontab -e`) run at 9am and append to a log:
|
|
243
344
|
|
|
244
345
|
```cron
|
|
245
|
-
0 9 * * * /
|
|
346
|
+
0 9 * * * /home/you/.local/bin/youpdated check >> ~/youpdated.log 2>&1
|
|
246
347
|
```
|
|
247
348
|
|
|
248
349
|
**Keep an RSS feed fresh** for a reader to poll. Note that `--rss` writes that run's items, so a plain `check --rss` leaves almost an empty file. For a feed that always holds a rolling window, ask for it. `--no-save` keeps this from interfering with your daily incremental run:
|
|
249
350
|
|
|
250
351
|
```cron
|
|
251
|
-
0 * * * * /
|
|
352
|
+
0 * * * * /home/you/.local/bin/youpdated check --all --since 30d --no-save --rss ~/feeds/youpdated.xml
|
|
252
353
|
```
|
|
253
354
|
|
|
254
355
|
**macOS launchd**: save as `~/Library/LaunchAgents/com.youpdated.check.plist`, then `launchctl load ~/Library/LaunchAgents/com.youpdated.check.plist`:
|
|
@@ -259,7 +360,7 @@ Once a day is plenty, most of these sources change slowly, and conditional reque
|
|
|
259
360
|
<key>Label</key><string>com.youpdated.check</string>
|
|
260
361
|
<key>ProgramArguments</key>
|
|
261
362
|
<array>
|
|
262
|
-
<string>/
|
|
363
|
+
<string>/Users/you/.local/bin/youpdated</string>
|
|
263
364
|
<string>check</string>
|
|
264
365
|
<string>--rss</string>
|
|
265
366
|
<string>/Users/you/feeds/youpdated.xml</string>
|
|
@@ -275,7 +376,8 @@ Once a day is plenty, most of these sources change slowly, and conditional reque
|
|
|
275
376
|
| Symptom | Cause and fix |
|
|
276
377
|
| --- | --- |
|
|
277
378
|
| `Config error: no config file found` | Run `youpdated init`, or pass `--config PATH`. |
|
|
278
|
-
| First run printed nothing | Working as intended
|
|
379
|
+
| First run printed nothing | Working as intended: it recorded a baseline. Run `youpdated check --all` to see current items. |
|
|
380
|
+
| A newly added target printed nothing | Same as above, for that one target. `youpdated check --all -s <source>` shows its current items. |
|
|
279
381
|
| `--all` shows fewer items than expected | Nothing is wrong; sources cap how much history they expose (10–20 items each). |
|
|
280
382
|
| A source appears in the yellow `problems` panel | That one source failed; the rest of the run still completed. Re-run with `-v` to see the request and status. |
|
|
281
383
|
| `unknown source 'X'` | Check spelling against `youpdated sources`. |
|