package main import ( "bufio" "encoding/json" "fmt" "io" "net/http" "os" "strings" "time" "github.com/google/uuid" ) type OpenAIRequest struct { Messages []Message `json:"messages"` Stream bool `json:"stream"` Model string `json:"model"` } type Message struct { Role string `json:"role"` Content string `json:"content"` } type MerlinRequest struct { Attachments []interface{} `json:"attachments"` ChatId string `json:"chatId"` Language string `json:"language"` Message struct { Content string `json:"content"` Context string `json:"context"` ChildId string `json:"childId"` Id string `json:"id"` ParentId string `json:"parentId"` } `json:"message"` Metadata struct { LargeContext bool `json:"largeContext"` MerlinMagic bool `json:"merlinMagic"` ProFinderMode bool `json:"proFinderMode"` WebAccess bool `json:"webAccess"` } `json:"metadata"` Mode string `json:"mode"` Model string `json:"model"` } type MerlinResponse struct { Data struct { Content string `json:"content"` } `json:"data"` } type OpenAIResponse struct { Id string `json:"id"` Object string `json:"object"` Created int64 `json:"created"` Model string `json:"model"` Choices []struct { Delta struct { Content string `json:"content"` } `json:"delta"` Index int `json:"index"` FinishReason string `json:"finish_reason"` } `json:"choices"` } type TokenResponse struct { IdToken string `json:"idToken"` } func getEnvOrDefault(key, defaultValue string) string { if value := os.Getenv(key); value != "" { return value } return defaultValue } func getToken() (string, error) { tokenReq := struct { UUID string `json:"uuid"` }{ UUID: getEnvOrDefault("UUID", ""), } tokenReqBody, _ := json.Marshal(tokenReq) resp, err := http.Post( "https://getmerlin-main-server.vercel.app/generate", "application/json", strings.NewReader(string(tokenReqBody)), ) if err != nil { return "", err } defer resp.Body.Close() var tokenResp TokenResponse if err := json.NewDecoder(resp.Body).Decode(&tokenResp); err != nil { return "", err } return tokenResp.IdToken, nil } func Handler(w http.ResponseWriter, r *http.Request) { authToken := r.Header.Get("Authorization") envToken := getEnvOrDefault("AUTH_TOKEN", "") if envToken != "" && authToken != "Bearer "+envToken { http.Error(w, "Unauthorized", http.StatusUnauthorized) return } if r.URL.Path != "/hf/v1/chat/completions" { w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) fmt.Fprintf(w, `{"status":"GetMerlin2Api Service Running...","message":"MoLoveSze..."}`) return } if r.Method != http.MethodPost { http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) return } var openAIReq OpenAIRequest if err := json.NewDecoder(r.Body).Decode(&openAIReq); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } var contextMessages []string for i := 0; i < len(openAIReq.Messages)-1; i++ { msg := openAIReq.Messages[i] contextMessages = append(contextMessages, fmt.Sprintf("%s: %s", msg.Role, msg.Content)) } context := strings.Join(contextMessages, "\n") merlinReq := MerlinRequest{ Attachments: make([]interface{}, 0), ChatId: generateV1UUID(), Language: "AUTO", Message: struct { Content string `json:"content"` Context string `json:"context"` ChildId string `json:"childId"` Id string `json:"id"` ParentId string `json:"parentId"` }{ Content: openAIReq.Messages[len(openAIReq.Messages)-1].Content, Context: context, ChildId: generateUUID(), Id: generateUUID(), ParentId: "root", }, Mode: "UNIFIED_CHAT", Model: openAIReq.Model, Metadata: struct { LargeContext bool `json:"largeContext"` MerlinMagic bool `json:"merlinMagic"` ProFinderMode bool `json:"proFinderMode"` WebAccess bool `json:"webAccess"` }{ LargeContext: false, MerlinMagic: false, ProFinderMode: false, WebAccess: false, }, } token, err := getToken() if err != nil { http.Error(w, "Failed to get token: "+err.Error(), http.StatusInternalServerError) return } client := &http.Client{} merlinReqBody, _ := json.Marshal(merlinReq) req, _ := http.NewRequest("POST", "https://arcane.getmerlin.in/v1/thread/unified", strings.NewReader(string(merlinReqBody))) req.Header.Set("Content-Type", "application/json") req.Header.Set("Accept", "text/event-stream, text/event-stream") req.Header.Set("Authorization", "Bearer "+token) req.Header.Set("x-merlin-version", "web-merlin") req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36") req.Header.Set("sec-ch-ua", `"Not(A:Brand";v="99", "Microsoft Edge";v="133", "Chromium";v="133"`) req.Header.Set("sec-ch-ua-mobile", "?0") req.Header.Set("sec-ch-ua-platform", "Windows") req.Header.Set("Sec-Fetch-Site", "same-site") req.Header.Set("Sec-Fetch-Mode", "cors") req.Header.Set("Sec-Fetch-Dest", "empty") req.Header.Set("host", "arcane.getmerlin.in") var flusher http.Flusher if openAIReq.Stream { var ok bool flusher, ok = w.(http.Flusher) if !ok { http.Error(w, "Streaming unsupported!", http.StatusInternalServerError) return } w.Header().Set("Content-Type", "text/event-stream") w.Header().Set("Cache-Control", "no-cache") w.Header().Set("Connection", "keep-alive") w.Header().Set("X-Accel-Buffering", "no") w.Header().Set("Transfer-Encoding", "chunked") defer func() { if flusher != nil { flusher.Flush() } }() } else { w.Header().Set("Content-Type", "application/json") } resp, err := client.Do(req) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } defer resp.Body.Close() if !openAIReq.Stream { var fullContent string reader := bufio.NewReader(resp.Body) for { line, err := reader.ReadString('\n') if err != nil { if err == io.EOF { break } continue } line = strings.TrimSpace(line) if strings.HasPrefix(line, "event: message") { dataLine, err := reader.ReadString('\n') if err != nil { continue } dataLine = strings.TrimSpace(dataLine) if strings.HasPrefix(dataLine, "data: ") { dataStr := strings.TrimPrefix(dataLine, "data: ") var merlinResp MerlinResponse if err := json.Unmarshal([]byte(dataStr), &merlinResp); err != nil { continue } if merlinResp.Data.Content != " " { fullContent += merlinResp.Data.Content } } } } response := map[string]interface{}{ "id": generateUUID(), "object": "chat.completion", "created": getCurrentTimestamp(), "model": openAIReq.Model, "choices": []map[string]interface{}{ { "message": map[string]interface{}{ "role": "assistant", "content": fullContent, }, "finish_reason": "stop", "index": 0, }, }, } json.NewEncoder(w).Encode(response) return } reader := bufio.NewReader(resp.Body) for { line, err := reader.ReadString('\n') if err != nil { if err == io.EOF { break } continue } if strings.HasPrefix(line, "event: message") { dataLine, _ := reader.ReadString('\n') var merlinResp MerlinResponse json.Unmarshal([]byte(strings.TrimPrefix(dataLine, "data: ")), &merlinResp) if merlinResp.Data.Content != "" { openAIResp := OpenAIResponse{ Id: generateUUID(), Object: "chat.completion.chunk", Created: getCurrentTimestamp(), Model: openAIReq.Model, Choices: []struct { Delta struct { Content string `json:"content"` } `json:"delta"` Index int `json:"index"` FinishReason string `json:"finish_reason"` }{{ Delta: struct { Content string `json:"content"` }{ Content: merlinResp.Data.Content, }, Index: 0, FinishReason: "", }}, } respData, _ := json.Marshal(openAIResp) fmt.Fprintf(w, "data: %s\n\n", string(respData)) flusher.Flush() } } } finalResp := OpenAIResponse{ Id: generateUUID(), Object: "chat.completion.chunk", Created: getCurrentTimestamp(), Model: openAIReq.Model, Choices: []struct { Delta struct { Content string `json:"content"` } `json:"delta"` Index int `json:"index"` FinishReason string `json:"finish_reason"` }{{ Delta: struct { Content string `json:"content"` }{Content: ""}, Index: 0, FinishReason: "stop", }}, } respData, _ := json.Marshal(finalResp) fmt.Fprintf(w, "data: %s\n\n", string(respData)) fmt.Fprintf(w, "data: [DONE]\n\n") flusher.Flush() } func generateUUID() string { return uuid.New().String() } func generateV1UUID() string { uuidObj := uuid.Must(uuid.NewUUID()) return uuidObj.String() } func getCurrentTimestamp() int64 { return time.Now().Unix() } func main() { port := getEnvOrDefault("PORT", "7860") http.HandleFunc("/", Handler) fmt.Printf("Server starting on port %s...\n", port) if err := http.ListenAndServe(":"+port, nil); err != nil { fmt.Printf("Error starting server: %v\n", err) } }