Skip to content

JonathanGriffe/archiver

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

archiver

Automated media archiver: a background service that automatically downloads media from connected sources and helps you sort them with a UI.

How it works

Detection and download are decoupled through a durable SQLite work queue — no external services, no broker, no Docker:

  • Detectors list a source's items, skip already-imported ones, and enqueue the rest into the queue (a table in the same SQLite DB as the dedup index).
  • Workers (a thread pool) claim jobs, download, verify, and atomically file each item into the unsorted inbox, recording a content hash so nothing is duplicated. Delivery is at-least-once via short leases: a job stays claimed until it succeeds, and a crashed worker's lease lapses so the job is retried.
  • A source owns its availability: while unavailable, its detection is silent and its queued jobs simply aren't claimed (the pause), and idle workers park — no busy polling. A set_available(True) wakes everything and its backlog drains.

Because the queue lives in the shared DB, archiver folder enqueues even when the daemon isn't running; the daemon drains the backlog when it next runs.

Sources are not declared in the config file. They are added at runtime and persisted in the SQLite state DB, so they survive a reboot. Folders are a one-shot exception: they aren't persisted as sources. Recurring sources (gdrive/phone) are persisted and begin polling when the daemon next starts.

archiver folder ~/Downloads/to-archive       # scan + queue for import
archiver source add gdrive --name gdrive
archiver source list
archiver source remove gdrive

Interval sources all poll on one program-wide cadence (poll_interval_seconds in the config), not a per-source interval.

Install

Requires Python 3.11+. Install with pipx so the app gets its own isolated environment and the archiver command lands on your PATH. The UI and every source are included by default — no extras to pick:

pipx install "archiver @ git+<repo-url>"
archiver setup

archiver setup writes a starter config, enables run-at-login, and launches the app. Launching the app starts both the tray/window and the background daemon (a separate process the tray supervises) — and the same happens automatically at every login. That's the whole install.

pipx install can't run code on its own, so the one-time archiver setup does the config + autostart + launch. After that it's automatic.

Works on Windows, macOS, and Linux. On Windows/macOS, tkinter (for the UI) ships with the python.org installer. On Linux, the tray additionally needs the system packages python3-tk and gir1.2-ayatanaappindicator3-0.1.

Prefer to do it by hand, or run headless? The pieces setup orchestrates are also separate commands:

archiver init                # write a starter config
archiver autostart install   # run the app at login
archiver ui                  # launch tray + window (also starts the daemon)
archiver run                 # run just the daemon in the foreground

Quit from the tray's Exit to stop the app and its daemon; otherwise it stops with the machine.

Setting up the Google Drive source

The Google Drive source reads media from your Drive over the Drive API. Because Google requires each app to identify itself with its own OAuth credentials, you create a small (free) Google Cloud "app" once, paste its credentials into the archiver, and grant access from your browser. You stay the only user of your own app, so no Google review/verification is ever required.

1. Dependencies

The Google Drive client libraries are installed by default — nothing extra to do.

2. Create a Google Cloud app (one-time)

In the Google Cloud Console:

  1. Create a project (top bar → project picker → New Project).
  2. Enable the Drive API: APIs & Services → Library → search Google Drive API → Enable.
  3. Configure the OAuth consent screen (APIs & Services → OAuth consent screen):
    • User type: External.
    • Fill in the app name and your email.
    • Scopes: add .../auth/drive.readonly (needed to download file content).
    • Test users: add your own Google account. Leave the app in Testing — you don't need to publish it.
  4. Create credentials (APIs & Services → Credentials → Create credentials → OAuth client ID):
    • Application type: Desktop app.
    • This gives you a Client ID and Client secret.

3. Save the client credentials

The Client ID and Client secret identify your Cloud app and are shared by every Google Drive source, so they're stored once as Google Drive settings. Open the UI, go to Settings → Google Drive, paste both values, and click Save:

archiver ui        # or launch the tray app

4. Add a source (this connects the account)

Each Google Drive source is tied to one Google account. Adding a source runs the OAuth consent flow: your browser opens Google's sign-in/consent screen, and on success the account's refresh token is stored with that source.

archiver source add gdrive --name my-drive

(Because the app is in Testing you'll see an "unverified app" warning — continue past it, since it's your own app.) The archiver then fetches fresh access tokens from the stored refresh token automatically — no further sign-in needed — and the daemon begins polling the source on its next poll cycle.

To connect a second account, add another source with a different --name.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors