Track and send notifications when individuals are added or removed from a compatible municipal jail roster jail.jackiefallsoffchair.rip
Find a file
kurtis 27085d5e0f
Some checks are pending
Build and Push Docker Image / build (push) Waiting to run
Add changelog
2026-01-16 12:54:26 -05:00
.forgejo/workflows use Forgejo as registry 2026-01-15 17:58:54 -05:00
templates v1.0.0 release! 2026-01-16 12:50:21 -05:00
.dockerignore add dockerfile and Forgejo builds 2026-01-15 17:56:16 -05:00
CHANGELOG.md Add changelog 2026-01-16 12:54:26 -05:00
Dockerfile add dockerfile and Forgejo builds 2026-01-15 17:56:16 -05:00
entrypoint.sh Add single container option 2026-01-15 17:52:22 -05:00
jailarr.py improve changes display 2026-01-15 20:20:03 -05:00
README.md misc small fixes. prep for 1.0.0 2026-01-16 12:47:44 -05:00
web.py Add "awards" feature 2026-01-15 20:52:05 -05:00

👮 Jailarr

A Python-based monitoring system that tracks and stores MyOCV-based jail inmate rosters, and displays them in a simple web interface. It also sends real-time notifications via Apprise (supporting 80+ notification services).

Features

  • Multi-Agency Support — Monitor multiple jail rosters simultaneously
  • Real-time Monitoring — Customizable check interval (default: 1 hour)
  • Modern Web Interface — Simple and intuitive web interface
  • Booking Alerts — Sends notifications with mugshot photos for new arrests
  • Release Tracking — Automatically detects and logs when inmates are released
  • Change Detection — Tracks updates to charges, mugshots, and other inmate details
  • Mugshot Versioning — Detects mugshot changes via image hashing and preserves old versions
  • Image Archiving — Downloads and stores inmate mugshots locally
  • Change History — Full audit log of all record modifications
  • Inmate Awards — Optionally shows a small badge for inmates that excel in certain areas (enable it to find out more)
  • Flexible Notifications — Supports Telegram, Discord, Slack, email, Pushover, and 80+ other services via Apprise
  • Docker Support — Easy deployment with Docker Compose

Configuration

The monitor is configured through environment variables:

Core Settings

Variable Description Required
JSON_URLS Agency JSON endpoint(s), comma or newline separated Yes
APPRISE_URLS Notification service URL(s), comma-separated No
DB_PATH Path to SQLite database file No (default: /data/inmates.db)
CHECK_INTERVAL Time between scans in seconds No (default: 3600 (1 hour))
WEB_PORT Port for web server No (default: 5000)
ENABLE_AWARDS Enable inmate awards No (default: false)

Notification Settings

Control which notification types are sent. Set to false to disable.

Variable Description Default
NOTIFY_NEW New inmate bookings true
NOTIFY_MUGSHOT Mugshot updates true
NOTIFY_CHARGES Charges updates false
NOTIFY_UPDATES Other field updates false
NOTIFY_STARTUP Send a message when the service starts true

Note: If APPRISE_URLS is not set, all notifications are disabled and the monitor runs in silent/archive mode.

Notification Services (Apprise)

Jailarr uses Apprise for notifications. Configure one or more services via URL:

Service URL Format
Telegram tgram://bot_token/chat_id or tgram://bot_token/chat_id:topic_id
Discord discord://webhook_id/webhook_token
Slack slack://token_a/token_b/token_c/#channel
Email mailto://user:pass@gmail.com
Pushover pover://user_key@api_token
Ntfy ntfy://topic
Gotify gotify://hostname/token

Multiple services: Comma-separate URLs to notify multiple services simultaneously:

APPRISE_URLS=tgram://bot/chat,discord://id/token,ntfy://mytopic

See the full list of supported services.

Finding Your JSON URL

This app ONLY works with jail rosters that use the MyOCV platform. You must provide the JSON URL(s) for the roster(s) you want to monitor. The JSON URL usually follows this pattern:

https://cdn.myocv.com/ocvapps/{AGENCY_ID}/{RosterName}.json

Known JSON Endpoints

Municipality Agency ID JSON URL
Chippewa County, MI a20449768 https://cdn.myocv.com/ocvapps/a20449768/Chippewainmates.json
Dickinson County, MI a135649801 https://cdn.myocv.com/ocvapps/a135649801/Dickinsoninmates.json
Houghton County, MI a134149931 https://cdn.myocv.com/ocvapps/a134149931/Houghtoninmates.json
Mackinac County, MI a109249781 https://cdn.myocv.com/ocvapps/a109249781/Mackinacinmates.json
Marquette County, MI a39949855 https://cdn.myocv.com/ocvapps/a39949855/Marquetteinmates.json

Different agencies may have slightly different JSON formats. Jailarr automatically normalizes field names and date formats across all supported agencies.

How to find your JSON URL

This is a somewhat complex task. Full writeup to come.

Notifications

Notification Types

Event Title Includes Photo
New booking 🚨 New Inmate Booking Yes
Mugshot updated 📷 Mugshot Updated Yes
Charges updated ⚖️ Charges Updated No
Record updated 📝 Inmate Record Updated No

First Run Behavior

On the first run (empty database), all inmates are added silently without sending notifications. This prevents a flood of alerts when initially populating the database. A startup message is still sent to confirm the monitor is online.

Example Notification

🚨 New Inmate Booking

Name: Smith, John

Age: 35
Gender: M
Booking Date: 2026-01-15 10:30:00

Charges:
OWI - OPERATING WHILE INTOXICATED - 1000.00
DRIVING WHILE LICENSE SUSPENDED - 500.00

Local Installation

Prerequisites

  • Python 3.11+
  • pip
  1. Clone the repository:

    git clone https://github.com/yourusername/jailarr.git
    cd jailarr
    
  2. Install dependencies:

    pip install requests apprise python-dateutil flask
    
  3. Set environment variables:

    # Single agency
    export JSON_URLS="https://cdn.myocv.com/ocvapps/a39949855/Marquetteinmates.json"
    
    # Or multiple agencies (comma-separated)
    export JSON_URLS="https://cdn.myocv.com/ocvapps/a39949855/Marquetteinmates.json,https://cdn.myocv.com/ocvapps/a135649801/Dickinsoninmates.json"
    
    export APPRISE_URLS="tgram://your_bot_token/your_chat_id"
    export DB_PATH="./data/inmates.db"
    
  4. Run the monitor:

    python jailarr.py
    

Docker Deployment

Option 1: Using Pre-built Image (placeholder. images coming soon)

services:
  jailarr:
    image: placeholder-registry/jailarr:latest
    container_name: jailarr
    restart: unless-stopped
    environment:
      - JSON_URLS=https://cdn.myocv.com/ocvapps/a39949855/Marquetteinmates.json
      - APPRISE_URLS=tgram://bot_token/chat_id
      - CHECK_INTERVAL=3600
    ports:
      - "5000:5000"
    volumes:
      - ./data:/data

Option 2: Building the Image

# Build locally
docker build -t jailarr .

# Or with docker compose
docker compose build

Option 3: Mount Source Files (No Build)

If you prefer to mount the source files directly without building an image:

services:
  jailarr:
    image: python:3.11-slim
    container_name: jailarr
    restart: unless-stopped
    command: >
      sh -c "pip install requests apprise python-dateutil flask && sh /app/entrypoint.sh"
    environment:
      - PYTHONUNBUFFERED=1
      - JSON_URLS=https://cdn.myocv.com/ocvapps/a39949855/Marquetteinmates.json
      - APPRISE_URLS=tgram://bot_token/chat_id
      - DB_PATH=/app/data/inmates.db
      - CHECK_INTERVAL=3600
    ports:
      - "5000:5000"
    volumes:
      - ./jailarr:/app

Data Storage

The monitor stores data in two locations:

Database (/data/inmates.db)

inmates table:

Column Description
record_id Composite key: {agency}_{inmate_id}
agency Source roster (e.g., Marquette, Dickinson)
inmate_id Original ID from the source roster
name Inmate name
age, gender, race Demographics
height, weight Physical description (if available)
booking_date Date/time of booking
charges List of charges
arresting_agency Agency that made the arrest (if available)
image_url Original mugshot URL
image_hash MD5 hash for change detection
first_seen Unix timestamp when first detected
last_seen Unix timestamp of last scan
status active or released

change_history table:

Column Description
record_id Links to inmate
field_name Which field changed
old_value Previous value
new_value Updated value
changed_at Unix timestamp

Images (/data/images/)

  • Current mugshots: {arrest_no}.jpg
  • Previous versions: {arrest_no}_v1.jpg, {arrest_no}_v2.jpg, etc.