package models import ( "database/sql" "strings" "time" ) type SyncPair struct { ID int64 `db:"id" json:"id"` Name string `db:"name" json:"name"` SourceMachineID *int64 `db:"source_machine_id" json:"source_machine_id"` SourcePath string `db:"source_path" json:"source_path"` DestMachineID *int64 `db:"dest_machine_id" json:"dest_machine_id"` DestPath string `db:"dest_path" json:"dest_path"` Direction string `db:"direction" json:"direction"` RsyncFlags string `db:"rsync_flags" json:"rsync_flags"` ExcludePatterns string `db:"exclude_patterns" json:"exclude_patterns"` Enabled bool `db:"enabled" json:"enabled"` CreatedAt time.Time `db:"created_at" json:"created_at"` } type SyncPairRepository struct { db *sql.DB } func NewSyncPairRepository(db *sql.DB) *SyncPairRepository { return &SyncPairRepository{db: db} } func (r *SyncPairRepository) Create(sp *SyncPair) (int64, error) { res, err := r.db.Exec(` INSERT INTO sync_pairs (name, source_machine_id, source_path, dest_machine_id, dest_path, direction, rsync_flags, exclude_patterns, enabled) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, sp.Name, sp.SourceMachineID, sp.SourcePath, sp.DestMachineID, sp.DestPath, sp.Direction, sp.RsyncFlags, sp.ExcludePatterns, boolToInt(sp.Enabled), ) if err != nil { return 0, err } return res.LastInsertId() } func (r *SyncPairRepository) GetAll() ([]SyncPair, error) { rows, err := r.db.Query(` SELECT id, name, source_machine_id, source_path, dest_machine_id, dest_path, direction, rsync_flags, exclude_patterns, enabled, created_at FROM sync_pairs ORDER BY name`) if err != nil { return nil, err } defer rows.Close() var pairs []SyncPair for rows.Next() { var p SyncPair var srcID, dstID sql.NullInt64 if err := rows.Scan(&p.ID, &p.Name, &srcID, &p.SourcePath, &dstID, &p.DestPath, &p.Direction, &p.RsyncFlags, &p.ExcludePatterns, &p.Enabled, &p.CreatedAt); err != nil { return nil, err } if srcID.Valid { v := srcID.Int64 p.SourceMachineID = &v } if dstID.Valid { v := dstID.Int64 p.DestMachineID = &v } p.Enabled = intToBool(intToInt(p.Enabled)) pairs = append(pairs, p) } return pairs, rows.Err() } func intToInt(v interface{}) int { switch x := v.(type) { case int: return x case int64: return int(x) case bool: if x { return 1 } return 0 default: return 0 } } func (r *SyncPairRepository) GetByID(id int64) (*SyncPair, error) { var p SyncPair var srcID, dstID sql.NullInt64 err := r.db.QueryRow(` SELECT id, name, source_machine_id, source_path, dest_machine_id, dest_path, direction, rsync_flags, exclude_patterns, enabled, created_at FROM sync_pairs WHERE id = ?`, id).Scan( &p.ID, &p.Name, &srcID, &p.SourcePath, &dstID, &p.DestPath, &p.Direction, &p.RsyncFlags, &p.ExcludePatterns, &p.Enabled, &p.CreatedAt) if err != nil { return nil, err } if srcID.Valid { v := srcID.Int64 p.SourceMachineID = &v } if dstID.Valid { v := dstID.Int64 p.DestMachineID = &v } p.Enabled = intToBool(intToInt(p.Enabled)) return &p, nil } func (r *SyncPairRepository) Update(sp *SyncPair) error { _, err := r.db.Exec(` UPDATE sync_pairs SET name=?, source_machine_id=?, source_path=?, dest_machine_id=?, dest_path=?, direction=?, rsync_flags=?, exclude_patterns=?, enabled=? WHERE id=?`, sp.Name, sp.SourceMachineID, sp.SourcePath, sp.DestMachineID, sp.DestPath, sp.Direction, sp.RsyncFlags, sp.ExcludePatterns, boolToInt(sp.Enabled), sp.ID, ) return err } func (r *SyncPairRepository) Delete(id int64) error { _, err := r.db.Exec("DELETE FROM sync_pairs WHERE id = ?", id) return err } func (r *SyncPairRepository) GetEnabled() ([]SyncPair, error) { rows, err := r.db.Query(` SELECT id, name, source_machine_id, source_path, dest_machine_id, dest_path, direction, rsync_flags, exclude_patterns, enabled, created_at FROM sync_pairs WHERE enabled = 1`) if err != nil { return nil, err } defer rows.Close() var pairs []SyncPair for rows.Next() { var p SyncPair var srcID, dstID sql.NullInt64 if err := rows.Scan(&p.ID, &p.Name, &srcID, &p.SourcePath, &dstID, &p.DestPath, &p.Direction, &p.RsyncFlags, &p.ExcludePatterns, &p.Enabled, &p.CreatedAt); err != nil { return nil, err } if srcID.Valid { v := srcID.Int64 p.SourceMachineID = &v } if dstID.Valid { v := dstID.Int64 p.DestMachineID = &v } p.Enabled = true pairs = append(pairs, p) } return pairs, rows.Err() } func (sp *SyncPair) ExcludePatternsList() []string { if sp.ExcludePatterns == "" { return nil } var patterns []string for _, p := range strings.Split(sp.ExcludePatterns, "\n") { p = strings.TrimSpace(p) if p != "" { patterns = append(patterns, p) } } return patterns }