package db import ( "database/sql" "time" ) // LabelChecker wraps a database connection to check takedown labels. // Implements middleware.LabelChecker interface. type LabelChecker struct { db *sql.DB } // NewLabelChecker creates a new LabelChecker. func NewLabelChecker(database *sql.DB) *LabelChecker { return &LabelChecker{db: database} } // IsTakenDown checks if a (DID, repository) pair has an active takedown. func (lc *LabelChecker) IsTakenDown(did, repository string) (bool, error) { return IsTakenDown(lc.db, did, repository) } // IsTakenDown reports whether the given (did, repo) pair is currently taken // down, either by an exact-repo row or by a user-level row (repo=”). func IsTakenDown(db DBTX, did, repository string) (bool, error) { var exists bool err := db.QueryRow( `SELECT EXISTS( SELECT 1 FROM taken_down_subjects WHERE did = ? AND (repo = ? OR repo = '') )`, did, repository, ).Scan(&exists) return exists, err } // SetTakedown records a positive takedown for (src, did, repo). Idempotent: // re-applying updates the timestamp. func SetTakedown(db DBTX, src, did, repo string, cts time.Time) error { _, err := db.Exec( `INSERT INTO taken_down_subjects (src, did, repo, cts) VALUES (?, ?, ?, ?) ON CONFLICT(src, did, repo) DO UPDATE SET cts = excluded.cts`, src, did, repo, cts.UTC().Format(time.RFC3339), ) return err } // RemoveTakedown drops the takedown row for (src, did, repo). Idempotent. func RemoveTakedown(db DBTX, src, did, repo string) error { _, err := db.Exec( `DELETE FROM taken_down_subjects WHERE src = ? AND did = ? AND repo = ?`, src, did, repo, ) return err } // GetCursor returns the last persisted cursor for a labeler src (0 if none). func GetCursor(db DBTX, src string) (int64, error) { var cursor int64 err := db.QueryRow( `SELECT cursor FROM labeler_cursor WHERE src = ?`, src, ).Scan(&cursor) if err == sql.ErrNoRows { return 0, nil } return cursor, err } // SetCursor persists the cursor for a labeler src. func SetCursor(db DBTX, src string, cursor int64) error { _, err := db.Exec( `INSERT INTO labeler_cursor (src, cursor) VALUES (?, ?) ON CONFLICT(src) DO UPDATE SET cursor = excluded.cursor`, src, cursor, ) return err }