summaryrefslogtreecommitdiff
path: root/internal/store/repeater.go
diff options
context:
space:
mode:
authorspiperac <[email protected]>2026-06-15 06:42:13 +0200
committerspiperac <[email protected]>2026-06-15 06:42:13 +0200
commit0a477fd288d064d265395c88dbd0f261b723804e (patch)
tree9b129f8f41c907285b89ed8385679934bb59c14f /internal/store/repeater.go
Initial release
Diffstat (limited to 'internal/store/repeater.go')
-rw-r--r--internal/store/repeater.go103
1 files changed, 103 insertions, 0 deletions
diff --git a/internal/store/repeater.go b/internal/store/repeater.go
new file mode 100644
index 0000000..b433559
--- /dev/null
+++ b/internal/store/repeater.go
@@ -0,0 +1,103 @@
+package store
+
+import (
+ "fmt"
+)
+
+// RepeaterTab represents a saved repeater tab.
+type RepeaterTab struct {
+ ID int64
+ Name string
+ Host string
+ Port int
+ TLS bool
+ TabType string // "http" or "websocket"
+ RawRequest string
+ LastResponse string
+ Position int
+}
+
+// AllRepeaterTabs returns all saved repeater tabs ordered by position.
+func (s *Store) AllRepeaterTabs() ([]RepeaterTab, error) {
+ rows, err := s.db.Query(`
+ SELECT id, name, host, port, tls, COALESCE(tab_type, 'http'), raw_request, COALESCE(last_response, ''), position
+ FROM repeater_tabs
+ ORDER BY position ASC`)
+ if err != nil {
+ return nil, fmt.Errorf("store: query repeater tabs: %w", err)
+ }
+ defer rows.Close()
+
+ var tabs []RepeaterTab
+ for rows.Next() {
+ var tab RepeaterTab
+ var tlsFlag int
+ if err := rows.Scan(&tab.ID, &tab.Name, &tab.Host, &tab.Port, &tlsFlag, &tab.TabType, &tab.RawRequest, &tab.LastResponse, &tab.Position); err != nil {
+ return nil, fmt.Errorf("store: scan repeater tab: %w", err)
+ }
+ tab.TLS = tlsFlag == 1
+ if tab.TabType == "" {
+ tab.TabType = "http"
+ }
+ tabs = append(tabs, tab)
+ }
+ return tabs, rows.Err()
+}
+
+// SaveRepeaterTab inserts a new repeater tab and returns its ID.
+func (s *Store) SaveRepeaterTab(tab RepeaterTab) (int64, error) {
+ tabType := tab.TabType
+ if tabType == "" {
+ tabType = "http"
+ }
+ var id int64
+ err := s.write(func() error {
+ result, err := s.db.Exec(`
+ INSERT INTO repeater_tabs (name, host, port, tls, tab_type, raw_request, last_response, position)
+ VALUES (?, ?, ?, ?, ?, ?, ?, (SELECT COALESCE(MAX(position), 0) + 1 FROM repeater_tabs))`,
+ tab.Name, tab.Host, tab.Port, boolToInt(tab.TLS), tabType, tab.RawRequest, tab.LastResponse,
+ )
+ if err != nil {
+ return fmt.Errorf("store: save repeater tab: %w", err)
+ }
+ id, err = result.LastInsertId()
+ return err
+ })
+ return id, err
+}
+
+// UpdateRepeaterTab updates the request and response for an existing tab.
+func (s *Store) UpdateRepeaterTab(id int64, rawRequest, lastResponse string) error {
+ return s.write(func() error {
+ _, err := s.db.Exec(`
+ UPDATE repeater_tabs SET raw_request = ?, last_response = ? WHERE id = ?`,
+ rawRequest, lastResponse, id,
+ )
+ if err != nil {
+ return fmt.Errorf("store: update repeater tab: %w", err)
+ }
+ return nil
+ })
+}
+
+// RenameRepeaterTab updates the name of a tab.
+func (s *Store) RenameRepeaterTab(id int64, name string) error {
+ return s.write(func() error {
+ _, err := s.db.Exec(`UPDATE repeater_tabs SET name = ? WHERE id = ?`, name, id)
+ if err != nil {
+ return fmt.Errorf("store: rename repeater tab: %w", err)
+ }
+ return nil
+ })
+}
+
+// DeleteRepeaterTab removes a repeater tab by ID.
+func (s *Store) DeleteRepeaterTab(id int64) error {
+ return s.write(func() error {
+ _, err := s.db.Exec(`DELETE FROM repeater_tabs WHERE id = ?`, id)
+ if err != nil {
+ return fmt.Errorf("store: delete repeater tab: %w", err)
+ }
+ return nil
+ })
+}