Skip to content

Creating custom addons

randompersona1 edited this page Jan 26, 2026 · 6 revisions

Disclaimer: This page assumes the reader knows python, or is capable of looking up information about python

What are addons?

An addon is a python module that sits in the user data directory under usdb_syncer/addons. This means an addon may be:

  • a python file with any name
  • a folder containing a __init__.py file
  • a zip file containing one or more of the above

This is how it plays out:

.
└── addons/
    ├── addon1.zip/
    │   ├── addon1/
    │   │   ├── __init__.py
    │   │   ├── file1.py
    │   │   └── file2.py
    │   └── addon2/
    │       ├── __init__.py
    │       ├── file1.py
    │       └── file2.py
    ├── addon3/
    │   ├── __init__.py
    │   ├── file1.py
    │   └── file2.py
    └── addon4.py

The syncer imports all of these modules at startup in random order, thereby executing at the entrypoint of the module.

Note: during import of your addon module, the syncer is not guaranteed to be initialized. The main window does not exist yet, and the database has not been set up. You should not rely on any internals of the syncer except hooks (explained down below).

What can addons do?:

Since addons are executed in the syncer environment, they have full access to any and all internals. You can patch functions, change constants or literals, or do anything else. The syncer does not however guarantee that names are consistent across versions. You may want to perform a version check using usdb_syncer.__version__.

Addons are explicitly advised to use hooks to add features. Hooks are documented on this page. We encourage suggestions for new hooks via the Issues page.

Hooks

Hooks are defined in the hooks module or in the gui.hooks module

Hooks allow an addon to subscribe to a certain event. The syncer will call the addon when this event occurs.

gui.hooks.MainWindowDidLoad(usdb_syncer.gui.mw.MainWindow)

Called when the main window is fully set up. Passes an instance of the main window. This hook is not called if the main window is never created (for example, if the user merely ran usdb_syncer --version.

This hook is called before the main window is displayed, so that any performance hits here do not affect the responsiveness of the Qt event loop.

hooks.SongLoaderDidFinish(usdb_syncer.usdb_song.UsdbSong)

Called when a song has finished downloading. Passes an instance of that songs UsdbSong dataclass.

hooks.GetYtCookies(http.CookieJar)

available since 0.19.0

Called when the syncer attempts to retry downloading a song with cookies. Passes a cookiejar for addons to write to.

hooks.GetUsdbCookies(http.CookieJar)

available since 0.19.0

Called when the syncer attempts to login to USDB with cookies. Passes a cookiejar for addons to write to.

This hook may be called from the main event loop. It should therefore exit quickly.

hooks.DangerouslyUseYtCookies(collections.abc.MutableSet[str])

available since 0.19.0

Called when a youtube download has failed. The syncer checks if the strings in the passed set are in the yt-dlp error message. If so, it retries the download with cookies.

By default, the set contains some error messages so that age restricted videos are retried.

Using this hook is dangerous, as it may cause the youtube account of the cookies used to be banned if youtube decides you are downloading too much. We do not recommend use of this hook. We provide it for special cases on your own risk only.