|
| 1 | +package main |
| 2 | + |
| 3 | +import ( |
| 4 | + "database/sql" |
| 5 | + "fmt" |
| 6 | + "log" |
| 7 | + "os" |
| 8 | + "strings" |
| 9 | + "time" |
| 10 | + |
| 11 | + _ "modernc.org/sqlite" |
| 12 | +) |
| 13 | + |
| 14 | +func esc(s string) string { |
| 15 | + return "'" + strings.ReplaceAll(s, "'", "''") + "'" |
| 16 | +} |
| 17 | + |
| 18 | +func main() { |
| 19 | + sqliteDB, err := sql.Open("sqlite", "./bughunt.db?_pragma=foreign_keys(1)&_pragma=journal_mode(WAL)") |
| 20 | + if err != nil { |
| 21 | + log.Fatalf("Failed to open SQLite: %v", err) |
| 22 | + } |
| 23 | + defer sqliteDB.Close() |
| 24 | + |
| 25 | + f, err := os.Create("supabase_import.sql") |
| 26 | + if err != nil { |
| 27 | + log.Fatalf("Failed to create output file: %v", err) |
| 28 | + } |
| 29 | + defer f.Close() |
| 30 | + |
| 31 | + w := func(s string) { f.WriteString(s + "\n") } |
| 32 | + |
| 33 | + w("-- AutoAR Database Export for Supabase") |
| 34 | + w(fmt.Sprintf("-- Generated at: %s", time.Now().Format(time.RFC3339))) |
| 35 | + w("-- Instructions: Paste this into the Supabase SQL Editor and run it.") |
| 36 | + w("") |
| 37 | + w("-- Disable triggers for fast import") |
| 38 | + w("SET session_replication_role = replica;") |
| 39 | + w("") |
| 40 | + |
| 41 | + // 1. Domains |
| 42 | + w("-- DOMAINS TABLE") |
| 43 | + rows, _ := sqliteDB.Query(`SELECT id, domain, created_at, updated_at FROM domains`) |
| 44 | + count := 0 |
| 45 | + for rows.Next() { |
| 46 | + var id int |
| 47 | + var domain string |
| 48 | + var created_at, updated_at sql.NullString |
| 49 | + rows.Scan(&id, &domain, &created_at, &updated_at) |
| 50 | + ca := "NOW()"; if created_at.Valid { ca = esc(created_at.String) } |
| 51 | + ua := "NOW()"; if updated_at.Valid { ua = esc(updated_at.String) } |
| 52 | + w(fmt.Sprintf("INSERT INTO domains (id, domain, created_at, updated_at) VALUES (%d, %s, %s, %s) ON CONFLICT (domain) DO NOTHING;", id, esc(domain), ca, ua)) |
| 53 | + count++ |
| 54 | + } |
| 55 | + rows.Close() |
| 56 | + w(fmt.Sprintf("SELECT setval('domains_id_seq', COALESCE((SELECT MAX(id) FROM domains), 1));")) |
| 57 | + log.Printf("[+] Exported %d domains", count) |
| 58 | + w("") |
| 59 | + |
| 60 | + // 2. Subdomains |
| 61 | + w("-- SUBDOMAINS TABLE") |
| 62 | + rows, _ = sqliteDB.Query(`SELECT id, domain_id, subdomain, is_live, COALESCE(http_url,''), COALESCE(https_url,''), COALESCE(http_status,0), COALESCE(https_status,0), created_at, updated_at FROM subdomains`) |
| 63 | + count = 0 |
| 64 | + for rows.Next() { |
| 65 | + var id, domain_id, is_live, http_status, https_status int |
| 66 | + var subdomain, http_url, https_url string |
| 67 | + var created_at, updated_at sql.NullString |
| 68 | + rows.Scan(&id, &domain_id, &subdomain, &is_live, &http_url, &https_url, &http_status, &https_status, &created_at, &updated_at) |
| 69 | + ca := "NOW()"; if created_at.Valid { ca = esc(created_at.String) } |
| 70 | + ua := "NOW()"; if updated_at.Valid { ua = esc(updated_at.String) } |
| 71 | + isLive := "FALSE"; if is_live != 0 { isLive = "TRUE" } |
| 72 | + w(fmt.Sprintf("INSERT INTO subdomains (id, domain_id, subdomain, is_live, http_url, https_url, http_status, https_status, created_at, updated_at) VALUES (%d, %d, %s, %s, %s, %s, %d, %d, %s, %s) ON CONFLICT (subdomain) DO NOTHING;", id, domain_id, esc(subdomain), isLive, esc(http_url), esc(https_url), http_status, https_status, ca, ua)) |
| 73 | + count++ |
| 74 | + } |
| 75 | + rows.Close() |
| 76 | + w("SELECT setval('subdomains_id_seq', COALESCE((SELECT MAX(id) FROM subdomains), 1));") |
| 77 | + log.Printf("[+] Exported %d subdomains", count) |
| 78 | + w("") |
| 79 | + |
| 80 | + // 3. JS Files |
| 81 | + w("-- JS_FILES TABLE") |
| 82 | + rows, _ = sqliteDB.Query(`SELECT id, subdomain_id, js_url, COALESCE(content_hash,''), COALESCE(last_scanned,''), created_at, updated_at FROM js_files`) |
| 83 | + count = 0 |
| 84 | + for rows.Next() { |
| 85 | + var id, subdomain_id int |
| 86 | + var js_url, content_hash, last_scanned string |
| 87 | + var created_at, updated_at sql.NullString |
| 88 | + rows.Scan(&id, &subdomain_id, &js_url, &content_hash, &last_scanned, &created_at, &updated_at) |
| 89 | + ca := "NOW()"; if created_at.Valid { ca = esc(created_at.String) } |
| 90 | + ua := "NOW()"; if updated_at.Valid { ua = esc(updated_at.String) } |
| 91 | + ls := "NOW()"; if last_scanned != "" { ls = esc(last_scanned) } |
| 92 | + w(fmt.Sprintf("INSERT INTO js_files (id, subdomain_id, js_url, content_hash, last_scanned, created_at, updated_at) VALUES (%d, %d, %s, %s, %s, %s, %s) ON CONFLICT (js_url) DO NOTHING;", id, subdomain_id, esc(js_url), esc(content_hash), ls, ca, ua)) |
| 93 | + count++ |
| 94 | + } |
| 95 | + rows.Close() |
| 96 | + w("SELECT setval('js_files_id_seq', COALESCE((SELECT MAX(id) FROM js_files), 1));") |
| 97 | + log.Printf("[+] Exported %d JS files", count) |
| 98 | + w("") |
| 99 | + |
| 100 | + // 4. Keyhack Templates |
| 101 | + w("-- KEYHACK_TEMPLATES TABLE") |
| 102 | + rows, _ = sqliteDB.Query(`SELECT id, keyname, command_template, COALESCE(method,'GET'), url, COALESCE(header,''), COALESCE(body,''), COALESCE(description,''), COALESCE(notes,''), created_at, updated_at FROM keyhack_templates`) |
| 103 | + count = 0 |
| 104 | + for rows.Next() { |
| 105 | + var id int |
| 106 | + var keyname, command_template, method, url, header, body, description, notes string |
| 107 | + var created_at, updated_at sql.NullString |
| 108 | + rows.Scan(&id, &keyname, &command_template, &method, &url, &header, &body, &description, ¬es, &created_at, &updated_at) |
| 109 | + ca := "NOW()"; if created_at.Valid { ca = esc(created_at.String) } |
| 110 | + ua := "NOW()"; if updated_at.Valid { ua = esc(updated_at.String) } |
| 111 | + w(fmt.Sprintf("INSERT INTO keyhack_templates (id, keyname, command_template, method, url, header, body, description, notes, created_at, updated_at) VALUES (%d, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) ON CONFLICT (keyname) DO NOTHING;", id, esc(keyname), esc(command_template), esc(method), esc(url), esc(header), esc(body), esc(description), esc(notes), ca, ua)) |
| 112 | + count++ |
| 113 | + } |
| 114 | + rows.Close() |
| 115 | + w("SELECT setval('keyhack_templates_id_seq', COALESCE((SELECT MAX(id) FROM keyhack_templates), 1));") |
| 116 | + log.Printf("[+] Exported %d keyhack templates", count) |
| 117 | + w("") |
| 118 | + |
| 119 | + // 5. Scans |
| 120 | + w("-- SCANS TABLE") |
| 121 | + rows, _ = sqliteDB.Query(`SELECT id, scan_id, scan_type, target, status, COALESCE(channel_id,''), COALESCE(thread_id,''), COALESCE(message_id,''), current_phase, total_phases, COALESCE(phase_name,''), COALESCE(started_at,''), COALESCE(completed_at,''), last_update, COALESCE(command,''), created_at, updated_at FROM scans`) |
| 122 | + count = 0 |
| 123 | + for rows.Next() { |
| 124 | + var id, current_phase, total_phases int |
| 125 | + var scan_id, scan_type, target, status, channel_id, thread_id, message_id, phase_name, started_at, completed_at, last_update, command string |
| 126 | + var created_at, updated_at sql.NullString |
| 127 | + rows.Scan(&id, &scan_id, &scan_type, &target, &status, &channel_id, &thread_id, &message_id, ¤t_phase, &total_phases, &phase_name, &started_at, &completed_at, &last_update, &command, &created_at, &updated_at) |
| 128 | + ca := "NOW()"; if created_at.Valid { ca = esc(created_at.String) } |
| 129 | + ua := "NOW()"; if updated_at.Valid { ua = esc(updated_at.String) } |
| 130 | + sa := "NOW()"; if started_at != "" { sa = esc(started_at) } |
| 131 | + w(fmt.Sprintf("INSERT INTO scans (id, scan_id, scan_type, target, status, channel_id, thread_id, message_id, current_phase, total_phases, phase_name, started_at, last_update, command, created_at, updated_at) VALUES (%d, %s, %s, %s, %s, %s, %s, %s, %d, %d, %s, %s, %s, %s, %s, %s) ON CONFLICT (scan_id) DO NOTHING;", |
| 132 | + id, esc(scan_id), esc(scan_type), esc(target), esc(status), esc(channel_id), esc(thread_id), esc(message_id), current_phase, total_phases, esc(phase_name), sa, esc(last_update), esc(command), ca, ua)) |
| 133 | + count++ |
| 134 | + } |
| 135 | + rows.Close() |
| 136 | + w("SELECT setval('scans_id_seq', COALESCE((SELECT MAX(id) FROM scans), 1));") |
| 137 | + log.Printf("[+] Exported %d scans", count) |
| 138 | + w("") |
| 139 | + |
| 140 | + w("-- Re-enable triggers") |
| 141 | + w("SET session_replication_role = DEFAULT;") |
| 142 | + w("") |
| 143 | + w("-- Done!") |
| 144 | + |
| 145 | + log.Printf("[SUCCESS] SQL export written to: supabase_import.sql") |
| 146 | + log.Printf("Now: 1) Open Supabase SQL Editor 2) Paste the file contents 3) Click Run") |
| 147 | +} |
0 commit comments