Files
2026-01-10 20:07:35 +01:00

90 lines
1.8 KiB
Go

package main
import (
"database/sql"
"fmt"
"time"
_ "modernc.org/sqlite"
)
type Record struct {
ID int
Timestamp time.Time
IP string
}
type Store struct {
db *sql.DB
}
func NewStore(path string) (*Store, error) {
dsn := fmt.Sprintf("%s?_pragma=journal_mode(WAL)&_pragma=synchronous=NORMAL&_pragma=mmap_size=268435456", path)
db, err := sql.Open("sqlite", dsn)
if err != nil {
return nil, err
}
schema := `
CREATE TABLE IF NOT EXISTS ip_history (
id INTEGER PRIMARY KEY AUTOINCREMENT,
ts DATETIME DEFAULT CURRENT_TIMESTAMP,
ip TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_ts ON ip_history(ts DESC);
CREATE INDEX IF NOT EXISTS idx_ip ON ip_history(ip COLLATE NOCASE);`
if _, err := db.Exec(schema); err != nil {
return nil, err
}
return &Store{db: db}, nil
}
func (s *Store) GetLatest() (string, error) {
var ip string
err := s.db.QueryRow("SELECT ip FROM ip_history ORDER BY ts DESC LIMIT 1").Scan(&ip)
if err == sql.ErrNoRows {
return "", nil
}
return ip, err
}
func (s *Store) Insert(ip string) error {
_, err := s.db.Exec("INSERT INTO ip_history (ip, ts) VALUES (?, ?)", ip, time.Now().UTC())
return err
}
func (s *Store) FetchPage(query string, page, pageSize int) ([]Record, bool, error) {
offset := (page - 1) * pageSize
limit := pageSize + 1
q := query + "%"
if query == "" {
q = "%"
}
rows, err := s.db.Query(
"SELECT id, ts, ip FROM ip_history WHERE ip LIKE ? ORDER BY ts DESC LIMIT ? OFFSET ?",
q, limit, offset,
)
if err != nil {
return nil, false, err
}
defer rows.Close()
var records []Record
for rows.Next() {
var r Record
if err := rows.Scan(&r.ID, &r.Timestamp, &r.IP); err != nil {
return nil, false, err
}
records = append(records, r)
}
hasMore := len(records) > pageSize
if hasMore {
records = records[:pageSize]
}
return records, hasMore, nil
}