Skip to main content

HTTP server exposing local filesystem as a wcpan.drive feed API

Project description

wcpan.drive.feed

An HTTP server that watches local filesystem paths with inotify, computes file metadata lazily, and exposes a token-based change log API — similar to Google Drive's changes API. This enables clients to efficiently poll for incremental changes without full directory scans.

Features

  • Watches directories recursively via inotify (Linux only)
  • Computes MD5 hash, MIME type, and image/video dimensions per file
  • Token-based change log API: clients request only changes since their last cursor
  • Merges intermediate events (e.g. multiple modifies → single update; create+delete → skip)
  • No authentication (designed for intranet use)

Requirements

  • Linux (inotify)
  • Python 3.12+
  • libmagic1 and mediainfo system packages

Installation

# Install system dependencies
apt-get install libmagic1 mediainfo

# Install Python dependencies
make venv

Configuration

Create a YAML config file:

host: "0.0.0.0"
port: 8080
database_url: "/data/db/server.db"
watches:
  media: /mnt/media
  photos: /mnt/photos

Running

uv run -m wcpan.drive.feed --config=/path/to/server.yaml

The --config flag defaults to /data/server.yaml.

API

GET /api/v1/cursor

Returns the current change log cursor (the latest change ID).

{ "cursor": 42 }

GET /api/v1/changes?cursor=<int>

Returns all changes since the given cursor. Missing cursor defaults to 0. Invalid cursor returns HTTP 400.

{
  "cursor": 57,
  "changes": [
    {
      "removed": false,
      "node": {
        "id": "...",
        "parent_id": "...",
        "name": "image.jpg",
        "is_directory": false,
        "ctime": "2026-03-04T12:00:00+00:00",
        "mtime": "2026-03-04T12:00:00+00:00",
        "mime_type": "image/jpeg",
        "hash": "d41d8cd98f00b204e9800998ecf8427e",
        "size": 204800,
        "is_image": true,
        "is_video": false,
        "width": 1920,
        "height": 1080,
        "ms_duration": 0
      }
    },
    {
      "removed": true,
      "node_id": "..."
    }
  ]
}

Nodes appear in two phases: first with hash: "" immediately after detection, then again with the full hash/MIME/dimensions after metadata computation completes. Clients should treat a second update for the same node as the final state.

GET /api/v1/root

Returns the virtual super-root node (parent of all watch-root directories).

{
  "id": "00000000-0000-0000-0000-000000000000",
  "parent_id": null,
  "name": "",
  "is_directory": true,
  "ctime": "2026-03-04T12:00:00+00:00",
  "mtime": "2026-03-04T12:00:00+00:00",
  "mime_type": "",
  "hash": "",
  "size": 0,
  "is_image": false,
  "is_video": false,
  "width": 0,
  "height": 0,
  "ms_duration": 0
}

GET /api/v1/nodes/{id}/path

Returns the absolute filesystem path for a node.

{ "path": "/mnt/media/photos/image.jpg" }

Returns HTTP 404 if the node does not exist, HTTP 400 if the node is the super-root.

Development

# Run tests
make test

# Format code
make format

# Lint
make lint

How It Works

  1. On startup, the server checks the database schema version. A new database is initialized automatically; a version mismatch raises an error and stops the server. Then it scans all configured watch paths and inserts/updates nodes in the local SQLite database.
  2. watchdog monitors each path for filesystem events (create, modify, delete, move).
  3. File metadata (MD5, MIME type, image/video dimensions) is computed in a ProcessPoolExecutor to avoid blocking the event loop.
  4. Every change is appended to a changes table. The /changes endpoint merges overlapping events per node — the last event wins — so clients always see the effective state.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

wcpan_drive_feed-1.0.1.tar.gz (92.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

wcpan_drive_feed-1.0.1-py3-none-any.whl (20.1 kB view details)

Uploaded Python 3

File details

Details for the file wcpan_drive_feed-1.0.1.tar.gz.

File metadata

  • Download URL: wcpan_drive_feed-1.0.1.tar.gz
  • Upload date:
  • Size: 92.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.11 {"installer":{"name":"uv","version":"0.10.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for wcpan_drive_feed-1.0.1.tar.gz
Algorithm Hash digest
SHA256 48262caeed8f1e142b64cbaceaa12223085e13e8bf08c47c3b07fc78ba009240
MD5 7e98f095c223eb9706d7f6fc7d171250
BLAKE2b-256 56513e47f35889fefaf8f6a901be0a87fa1e712ac76438cb9abfc2bdef3f7a95

See more details on using hashes here.

File details

Details for the file wcpan_drive_feed-1.0.1-py3-none-any.whl.

File metadata

  • Download URL: wcpan_drive_feed-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 20.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.11 {"installer":{"name":"uv","version":"0.10.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for wcpan_drive_feed-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 3a463b32d80edd9b4f9169be7801f52e2dceeca23b25e164c7715274e208daae
MD5 c2a5d15c8eb30d0e1e60eb6e9bb8ddcb
BLAKE2b-256 c990394c99aeca1c6849e01b542e8aabd7676635722673b02a62326e2e4d844b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page