Configurable, real-time alerts for your discogs wantlist
Project description
Discogs Alert
Customised, real-time alerting for your hard-to-find wantlist items.
discogs-alert enables you to configure ~real-time alerts that notify you the moment a hard-to-find release goes on sale. The project is designed to require as little effort as possible: you customise your preference once, upfront, and then sit back and wait for a notification.
discogs-alert enables both global and fine-grained customisation of your preferences (including price thresholds, minimum seller rating, minimum media / sleeve conditions, and countries from which you either do or don't want to receive alerts). You'll only ever get notified if a record goes on sale that really matches what you're looking for.
If you have suggestions or ideas, please reach out! So far I've bought more than 50 records thanks to
discogs_alert and I'd love to make it useful as possible for others.
Requirements
- Python >= 3.10
Installation & Setup
Four install paths, pick one:
Python (via pip)
pip install discogs-alert
macOS .app (drag-install, no Python required)
Download the latest .dmg from Releases, open it, drag discogs_alert.app into /Applications. The app self-updates via Sparkle whenever a new version is published.
On first launch, macOS Gatekeeper may say "discogs_alert can't be opened because Apple cannot check it for malicious software." Right-click the app → Open → confirm; you only have to do this once.
Docker
docker pull miggleball/discogs_alert:latest
docker run -d --env-file .env miggleball/discogs_alert:latest
The container runs python -m discogs_alert as its entrypoint; pass your config via env vars (DA_DISCOGS_TOKEN, DA_LIST_ID, …) in your .env file.
From source
git clone https://github.com/michaelhball/discogs_alert
cd discogs_alert
pip install -e .
For development you'll also want pip install -e '.[menubar]' if you're on a Mac and want the menu-bar app, plus poetry install to get the dev deps (pytest, ruff, tox, etc.).
Setup
Before you can use this project, there are a few more things that need to be setup.
Discogs access token
A Discogs access token allows discogs_alert to send requests to the discogs API on your behalf, and in particular it increases the rate at which you're allowed to make requests. This token can only be used to access the music database features of the Discogs API, not the marketplace, so there is no risk that you're accidentally granting control over the buying or selling of records. You can find more information here.
To create an access token, go to your Discogs settings and click on the Developer tab. There is a button on this page to generate a new token. For now, just copy this token to your computer.
Creating your wantlist
There are two different ways you can create a wantlist: 1) by connecting to one of your existing Discogs lists, or 2) by creating a local JSON file. The first option is easier, faster, and fits within your regular Discogs workflow. Both options support the same per-release filters (price threshold, media / sleeve condition); see below for the syntax in each case.
Discogs List
Using one of your existing Discogs lists only requires that you specify the ID of the list at runtime, the process for which is outlined in the usage section below. Ideally you should set up a list specifically for this purpose, as you'll be notified the moment any of the releases in your list go on sale. This approach makes it incredibly easy to add new releases to your wantlist: simply add a release to the specified list and discogs_alert will automatically identify this and add that release to those it's searching for on the next iteration.
Per-release filters in list comments
You can put @key=value directives in a list item's comment field to set per-release filters. Any other text in the comment is ignored. Recognised keys:
@max=N(or@price=N) — maximum total price (in your--currency).@media=...— minimum media condition (e.g.VG+,NM,M-,VERY_GOOD_PLUS).@sleeve=...— minimum sleeve condition (same vocabulary).
Examples (each one is a valid comment on a list item):
@max=500
Hot one! @max=300 @media=NM
@media=VG+ @sleeve=NM @max=80
Unknown keys are ignored; malformed values are dropped with a warning so a typo on one item won't break the rest of the loop.
Local JSON
Here is an example wantlist.json file:
[
{
"id": 1061046,
"display_title": "Deep² — Sphere",
"min_media_condition": "VERY_GOOD"
},
{
"id": 2247646,
"display_title": "Charanjit Singh — Ten Ragas to a Disco Beat",
"price_threshold": 500
}
]
The wantlist is a list of objects, each object representing a release. The only essential attributes are the id field, which can be found on each release's Discogs page, and the display_title, which is the name you give the release s.t. you will recognise it when you're notified.
There are a number of optional attributes that can be included for each release. The combination of all attributes applied to a given release are used as a filter, so you will only be notified if all conditions are met for a given listing item. In the above case, the user is looking for any VERY_GOOD or higher copies of the Deep² release, with no maximum price (e.g. an example scenario here is that there are currently no copies on the market, and the user wants to be notified as soon as one goes on sale). For the Charanjit Singh release, the user is looking for any copies on sale for less than €500. NB: the currency is determined later, at runtime. This is outlined in the usage section below.
Remember that all criteria for restricting your alerts also have global values, the setting of which is discussed in usage). This means that if you want the same filters for most releases you do not need to specify them for every single release in your wantlist.json. You can set the values once globally (when you run the program), and then set only those per-release values that differ from the global settings. Any filters specified in your wantlist.json will override the global values.
The possible optional filters are as follows:
price_threshold: maximum allowable price (excluding shipping)min_media_condition: minimum allowable media condition (one of'POOR','FAIR','GOOD','GOOD_PLUS','VERY_GOOD','VERY_GOOD_PLUS','NEAR_MINT', or'MINT')min_sleeve_condition: minimum allowable sleeve condition (one of'POOR','FAIR','GOOD','GOOD_PLUS','VERY_GOOD','VERY_GOOD_PLUS','NEAR_MINT', or'MINT')
Alerting
discogs_alert ships with three built-in alerters. Pick the one whose setup matches what you have on your phone — they all do the same job (one notification per matching listing). ntfy.sh is the recommended default because it has the least setup and no account dependencies.
Configuration goes in ~/.discogs_alert/config.toml (see examples/config.example.toml for the full schema). The [alerter] section selects which one and provides its credentials.
ntfy.sh (recommended — no account, no token)
ntfy.sh is the easiest alerter to set up. Pick a random hard-to-guess topic name (anyone with the topic name can read your notifications) and subscribe to that topic from the iOS, Android, desktop, or web app. Then in your config.toml:
[alerter]
type = "NTFY"
[alerter.ntfy]
topic = "your-secret-topic-here"
For privacy / reliability you can self-host ntfy: add server = "https://ntfy.example.com" (and optionally token = "..." if your server requires auth).
Pushbullet
Create an account at pushbullet.com and install the app on the device(s) where you want notifications. Then create an access token from your settings page. Configure:
[alerter]
type = "PUSHBULLET"
[alerter.pushbullet]
token = "..."
⚠️ Open the Pushbullet app at least once a month. If you don't, Pushbullet's API silently 401s requests because it considers the account dormant — your alerts will go nowhere with no error visible from
discogs_alert's side.
Telegram
To use Telegram you first need to create a custom bot. Easiest path is via @BotFather:
- Open Telegram on your phone, search for @BotFather, send
/startthen/newbot. Pick a name + username. BotFather replies with a bot token (looks like123456789:ABC-…). - Search for your new bot (by the username you chose) and send it
/start(any message works). - In a browser, open
https://api.telegram.org/bot<YOUR_BOT_TOKEN>/getUpdates. Find the"chat":{"id": …}field — that number is your chat_id.
Then configure:
[alerter]
type = "TELEGRAM"
[alerter.telegram]
token = "..."
chat_id = "..."
Adding more alerters (plugin authors)
discogs_alert discovers alerters dynamically via the discogs_alert.alerters Python entry-point group. To ship a new alerter as a separate package, subclass discogs_alert.alert.base.Alerter and register the class in your package's pyproject.toml:
[project.entry-points."discogs_alert.alerters"]
ntfy = "discogs_alert_ntfy:NtfyAlerter"
After pip install discogs-alert-ntfy, [alerter] type = "NTFY" becomes selectable in your config.toml. The entry-point name (uppercased) is the value of type. Your alerter is responsible for reading its own config (env vars, a config file section, etc.).
For a step-by-step guide and a copy-and-rename starter package, see docs/writing-an-alerter.md and examples/discogs-alert-alerter-template/.
Usage
discogs_alert can be run as a Python process or as a Docker container. Either way, the service polls your wantlist on a schedule, checks each release on the Discogs marketplace, and sends you a notification if any release (satisfying your filters) is for sale. Leave it running to be most effective.
Configuration lives in ~/.discogs_alert/config.toml (or wherever --config points). See examples/config.example.toml for the full schema. Any field can be overridden by a DA_* environment variable — handy for Docker / launchd / CI without committing secrets.
Python
$ cp examples/config.example.toml ~/.discogs_alert/config.toml
$ $EDITOR ~/.discogs_alert/config.toml # fill in your token, list_id, alerter
$ python -m discogs_alert
A few CLI helpers exist for debugging:
-c/--config <path>— point at a non-default config file.-O/--once— run the loop once and exit (use with cron / launchd / systemd-timer).-V/--verbose— DEBUG-level logs.-l/--log-level=<DEBUG|INFO|WARNING|ERROR>— explicit log-level override.--validate-config— load the config, print a one-line summary, exit.--print-config— load the config, dump the resolved values as JSON, exit.--version
Run python -m discogs_alert --help for the full list.
Docker
$ docker run -d --env-file .env miggleball/discogs_alert:latest
Your .env file should set the required DA_* variables. Minimal example:
DA_DISCOGS_TOKEN=<discogs_access_token>
DA_LIST_ID=<discogs_list_id>
DA_ALERTER_TYPE=NTFY
DA_NTFY_TOPIC=<your-ntfy-topic>
The -d flag detaches the container so it runs in the background.
Extras
You can add to or change your wantlist (Discogs list or local JSON) while the service is running; updates are picked up on the next iteration.
Each matching listing produces one notification — title is the release's display title, body is the listing URL. Deduplication is local: discogs_alert records every successful alert in ~/.discogs_alert/state.db (configurable via runtime.state_path in config.toml) and won't re-alert across iterations.
The full set of knobs lives in examples/config.example.toml — global filters (seller rating, media / sleeve condition, country whitelist / blacklist), runtime tuning (max_concurrency, prune_after_days, stats_gate), and per-alerter config. Per-release overrides go in your wantlist JSON or as @key=value directives in Discogs list comments (see above).
Full Example
A realistic ~/.discogs_alert/config.toml for a user driven by a Discogs list, who wants verbose logs, no minimum seller rating, a global minimum media condition of VERY_GOOD, and who doesn't want to consider sellers from the UK or US:
discogs_token = "<discogs_access_token>"
[wantlist]
list_id = <list_id>
[seller]
min_rating = 0 # turn off the seller-rating gate
[record]
min_media_condition = "VERY_GOOD"
[country_filters]
blacklist = ["UK", "US"]
[alerter]
type = "NTFY"
[alerter.ntfy]
topic = "<your-secret-topic>"
[runtime]
verbose = true
Running as a cron job
For low-effort always-on use, run discogs_alert as a cron job — set up your config.toml once and let cron schedule the iterations. Run crontab -e and add:
*/10 * * * * source ~/.bash_profile; python -m discogs_alert --once >> <path_to_log_file>.log 2>&1
discogs_alert runs every 10 minutes and logs to the specified file. tail -f <path_to_log_file>.log to follow.
See here for more on cron / crontab.
Running as a macOS launchd daemon
On macOS, the cleanest "always-on" path is a launchd agent — survives logout, doesn't need a terminal open, integrates with macOS power management. A starter template lives at docker/launchd/com.discogsalert.plist.template. Replace the placeholder paths, drop the file at ~/Library/LaunchAgents/com.discogsalert.plist, and launchctl load it. See the comments in the template for the exact recipe.
launchd timers pause while the Mac sleeps; for true 24/7 monitoring, run discogs_alert on an always-on box (Raspberry Pi, NAS, home server) instead.
macOS menu-bar app
For a lightweight GUI with status, "check now", and quick links to your config + state files, install the menu-bar extra and launch the app:
$ pip install 'discogs_alert[menubar]'
$ python -m discogs_alert.menubar
The menu-bar app is not the always-on path — closing it stops the loop. Use it interactively while at your Mac; pair it with launchd (above) for 24/7 monitoring.
Building a standalone .app / .dmg
If you'd rather drag-install a .app than pip install the package, the project ships a Makefile that wraps py2app and hdiutil:
$ make app # build dist/discogs_alert.app
$ make dmg # build dist/discogs_alert-X.Y.Z.dmg (the user-facing artifact)
The build uses a clean throwaway venv at .build-venv/ so unrelated packages on your outer Python don't pollute the bundle. End users only need to drag the .app from the DMG into /Applications — no Python install required.
Code signing: the
.appis unsigned by default. macOS Gatekeeper will prompt the user to right-click → Open on first launch. Code signing requires an Apple Developer ID ($99/yr); see Apple's notarization docs for the recipe.
Contributing
- Fork (https://github.com/michaelhball/discogs_alert/fork)
- Create your feature branch (git checkout -b feature/fooBar)
- Commit your changes (git commit -am 'Add some fooBar')
- Push to the branch (git push origin feature/fooBar)
- Create a new Pull Request
Setting up the dev environment
Ideally, you should work inside a virtual environment set up for this project. Once that's the case, simply run the following two commands to install all dependencies:
$ pip install --user poetry$ poetry install
And that's it! Until you want to propose your changes as a new PR. When that's the case you need to run the tests to make sure nothing has broken, which you can do simply by running $ tox in the project's root directory.
Author
License
This project is licensed under the MIT License - see the LICENSE file for details.
Housekeeping
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file discogs_alert-0.1.0.tar.gz.
File metadata
- Download URL: discogs_alert-0.1.0.tar.gz
- Upload date:
- Size: 54.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d8dd854cf07634a576a86b580e85fb88ba20a667da11ca522e8c531ec8355509
|
|
| MD5 |
ba4994d885e30f3ebf1ba6c038e2b44a
|
|
| BLAKE2b-256 |
fe98372e06b5fb3aed88edce8860f8ef51b7d1b712cbcd5ca9ae0757c1aa47c7
|
Provenance
The following attestation bundles were made for discogs_alert-0.1.0.tar.gz:
Publisher:
release.yml on michaelhball/discogs_alert
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
discogs_alert-0.1.0.tar.gz -
Subject digest:
d8dd854cf07634a576a86b580e85fb88ba20a667da11ca522e8c531ec8355509 - Sigstore transparency entry: 1520348437
- Sigstore integration time:
-
Permalink:
michaelhball/discogs_alert@8c564315b1317d7f7a10e16a2aac439bc2d919d9 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/michaelhball
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8c564315b1317d7f7a10e16a2aac439bc2d919d9 -
Trigger Event:
push
-
Statement type:
File details
Details for the file discogs_alert-0.1.0-py3-none-any.whl.
File metadata
- Download URL: discogs_alert-0.1.0-py3-none-any.whl
- Upload date:
- Size: 58.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
501ccf71eee84fb7f605f2669cf172cce483d0cb7eb411ca1bd65489ec7c13c7
|
|
| MD5 |
1f12b8d0f7b94a16958419003d02f76f
|
|
| BLAKE2b-256 |
be387e67b9c9b1038f0d965f372e29d60da2f3304605a923a2dfa046a9b5da1d
|
Provenance
The following attestation bundles were made for discogs_alert-0.1.0-py3-none-any.whl:
Publisher:
release.yml on michaelhball/discogs_alert
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
discogs_alert-0.1.0-py3-none-any.whl -
Subject digest:
501ccf71eee84fb7f605f2669cf172cce483d0cb7eb411ca1bd65489ec7c13c7 - Sigstore transparency entry: 1520348487
- Sigstore integration time:
-
Permalink:
michaelhball/discogs_alert@8c564315b1317d7f7a10e16a2aac439bc2d919d9 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/michaelhball
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8c564315b1317d7f7a10e16a2aac439bc2d919d9 -
Trigger Event:
push
-
Statement type: