akashyadav758
Harden monitor (gate all routes), swap ChatGPT backend to free-Chatgpt-api, clean repo
5c7f4b5
Raw
History Blame Contribute Delete
4.11 kB
package main
import (
"flag"
"fmt"
"log"
"net/http"
"os"
"sync"
"time"
)
var (
activeConvMu sync.Mutex
activeConvID string
)
func getActiveConversationID() string {
activeConvMu.Lock()
defer activeConvMu.Unlock()
return activeConvID
}
func setActiveConversationID(id string) {
activeConvMu.Lock()
activeConvID = id
activeConvMu.Unlock()
}
func clearActiveConversationID() {
activeConvMu.Lock()
activeConvID = ""
activeConvMu.Unlock()
}
func Start() {
loadConfig()
LoadCookiesFromFile()
promptFlag := flag.String("prompt", "", "Prompt to send to ChatGPT after the extension connects")
onceFlag := flag.Bool("once", false, "Send the prompt, print the response, then exit")
timeoutFlag := flag.Duration("timeout", cfg.Timeout(), "Maximum time to wait for extension/response")
flag.Parse()
http.HandleFunc("/", handleWS)
http.HandleFunc("/health", handleHealth)
http.HandleFunc("/api/ext/callback", handleCallback)
http.HandleFunc("/api/ext/reload", func(w http.ResponseWriter, r *http.Request) {
extMu.Lock()
conn := extConn
extMu.Unlock()
if conn == nil {
writeJSONStatus(w, http.StatusServiceUnavailable, map[string]any{"ok": false, "error": "extension not connected"})
return
}
err := conn.WriteJSON(WSMessage{
Method: "reload_extension",
})
if err != nil {
writeJSONStatus(w, http.StatusInternalServerError, map[string]any{"ok": false, "error": err.Error()})
return
}
writeJSON(w, map[string]any{"ok": true, "message": "reload request sent"})
})
http.HandleFunc("/api/conversation", func(w http.ResponseWriter, r *http.Request) {
convID := r.URL.Query().Get("conversation_id")
if convID == "" {
writeJSONStatus(w, http.StatusBadRequest, map[string]any{"ok": false, "error": "conversation_id required"})
return
}
token, err := getSessionToken()
if err != nil {
writeJSONStatus(w, http.StatusServiceUnavailable, map[string]any{"ok": false, "error": err.Error()})
return
}
res, err := callChatGPTAPI(apiCallParams{
URL: "https://chatgpt.com/backend-api/conversation/" + convID,
Method: "GET",
Headers: map[string]string{
"Authorization": "Bearer " + token,
},
}, cfg.APITimeout())
if err != nil {
writeJSONStatus(w, http.StatusInternalServerError, map[string]any{"ok": false, "error": err.Error()})
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(res.Status)
w.Write([]byte(res.Body))
})
http.HandleFunc("/api/chat", handleChat)
http.HandleFunc("/api/chat/bulk", handleChatBulk)
http.HandleFunc("/api/chat/edit", handleChatEdit)
http.HandleFunc("/api/chatgpt/test", handleChat)
http.HandleFunc("/api/sniffs", handleSniffs)
http.HandleFunc("/api/download", handleDownload)
http.HandleFunc("/v1/chat/completions", handleOpenAIChat)
http.HandleFunc("/api/cookies/status", func(w http.ResponseWriter, r *http.Request) {
writeJSON(w, map[string]any{
"ok": true,
"has_cookies": HasCookies(),
"last_sync": GetLastCookieSync().Format(time.RFC3339),
"cookie_header_len": len(GetCachedCookieHeader()),
"extension_connected": isExtensionConnected(),
})
})
if *promptFlag != "" {
go runPromptFromCLI(*promptFlag, *timeoutFlag, *onceFlag)
}
log.Printf("ChatGPT Agent listening on http://%s", cfg.ListenAddr)
log.Println("Reload the ChatGPT Browser Bridge extension if it is not connected.")
log.Println("Endpoints: GET/POST /api/chat, POST /api/chat/bulk, POST /api/chat/edit, GET /api/sniffs, GET /health")
if err := http.ListenAndServe(cfg.ListenAddr, nil); err != nil {
log.Fatal(err)
}
}
func runPromptFromCLI(prompt string, timeout time.Duration, once bool) {
log.Println("Waiting for extension API bridge connection...")
if !waitForExtension(timeout) {
log.Println("Extension did not connect before timeout")
if once {
os.Exit(1)
}
return
}
log.Printf("Sending prompt: %s", prompt)
text, _, err := sendChat(prompt)
if err != nil {
log.Printf("ChatGPT request failed: %v", err)
if once {
os.Exit(1)
}
return
}
fmt.Println(text)
if once {
os.Exit(0)
}
}