Niansuh commited on
Commit
24092aa
1 Parent(s): 2472bbe

Update main.go

Browse files
Files changed (1) hide show
  1. main.go +55 -76
main.go CHANGED
@@ -5,11 +5,19 @@ import (
5
  "bytes"
6
  "encoding/json"
7
  "io"
 
8
  "net/http"
 
9
 
10
  "github.com/gin-gonic/gin"
11
  )
12
 
 
 
 
 
 
 
13
  type OpenAIRequest struct {
14
  Model string `json:"model"`
15
  Messages []struct {
@@ -66,77 +74,58 @@ func chatWithDuckDuckGo(c *gin.Context, messages []struct {
66
  Role string `json:"role"`
67
  Content string `json:"content"`
68
  }, stream bool) {
69
- userAgent := "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:123.0) Gecko/20100101 Firefox/123.0"
70
- headers := map[string]string{
71
- "User-Agent": userAgent,
72
- "Accept": "text/event-stream",
73
- "Accept-Language": "de,en-US;q=0.7,en;q=0.3",
74
- "Accept-Encoding": "gzip, deflate, br",
75
- "Referer": "https://duckduckgo.com/",
76
- "Content-Type": "application/json",
77
- "Origin": "https://duckduckgo.com",
78
- "Connection": "keep-alive",
79
- "Cookie": "dcm=1",
80
- "Sec-Fetch-Dest": "empty",
81
- "Sec-Fetch-Mode": "cors",
82
- "Sec-Fetch-Site": "same-origin",
83
- "Pragma": "no-cache",
84
- "TE": "trailers",
85
- }
86
-
87
- statusURL := "https://duckduckgo.com/duckchat/v1/status"
88
- chatURL := "https://duckduckgo.com/duckchat/v1/chat"
89
 
90
- // get vqd_4
91
  req, err := http.NewRequest("GET", statusURL, nil)
92
  if err != nil {
93
- c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
 
94
  return
95
  }
96
-
97
  req.Header.Set("x-vqd-accept", "1")
98
- for key, value := range headers {
99
- req.Header.Set(key, value)
100
- }
101
 
102
- resp, err := http.DefaultClient.Do(req)
103
  if err != nil {
104
- c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
 
105
  return
106
  }
107
  defer resp.Body.Close()
108
 
109
  vqd4 := resp.Header.Get("x-vqd-4")
110
 
 
111
  payload := map[string]interface{}{
112
  "model": "gpt-3.5-turbo-0125",
113
  "messages": messages,
114
  }
115
-
116
  payloadBytes, err := json.Marshal(payload)
117
  if err != nil {
118
- c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
 
119
  return
120
  }
121
 
122
  req, err = http.NewRequest("POST", chatURL, bytes.NewBuffer(payloadBytes))
123
  if err != nil {
124
- c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
 
125
  return
126
  }
127
-
128
  req.Header.Set("x-vqd-4", vqd4)
129
- for key, value := range headers {
130
- req.Header.Set(key, value)
131
- }
132
 
133
- resp, err = http.DefaultClient.Do(req)
134
  if err != nil {
135
- c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
 
136
  return
137
  }
138
  defer resp.Body.Close()
139
 
 
140
  reader := bufio.NewReader(resp.Body)
141
  c.Header("Content-Type", "text/event-stream")
142
  c.Header("Cache-Control", "no-cache")
@@ -146,9 +135,7 @@ func chatWithDuckDuckGo(c *gin.Context, messages []struct {
146
  flusher, _ := c.Writer.(http.Flusher)
147
 
148
  var response OpenAIResponse
149
- var nonStreamResponse OpenAINonStreamResponse
150
  response.Choices = make([]OpenAIChoice, 1)
151
- nonStreamResponse.Choices = make([]OpenAINonStreamChoice, 1)
152
 
153
  var responseContent string
154
 
@@ -166,36 +153,12 @@ func chatWithDuckDuckGo(c *gin.Context, messages []struct {
166
  chunk := line[6:]
167
 
168
  if bytes.HasPrefix(chunk, []byte("[DONE]")) {
169
- if !stream {
170
- nonStreamResponse.Choices[0].Message.Content = responseContent
171
- nonStreamResponse.Choices[0].Message.Role = "assistant"
172
- nonStreamResponse.Choices[0].FinishReason = new(string)
173
- *nonStreamResponse.Choices[0].FinishReason = "stop"
174
- c.JSON(http.StatusOK, nonStreamResponse)
175
- return
176
- } else {
177
- stopData := OpenAIResponse{
178
- ID: "chatcmpl-9HOzx2PhnYCLPxQ3Dpa2OKoqR2lgl",
179
- Object: "chat.completion",
180
- Created: 1713934697,
181
- Model: "gpt-3.5-turbo-0125",
182
- Choices: []OpenAIChoice{
183
- {
184
- Index: 0,
185
- FinishReason: stringPtr("stop"),
186
- },
187
- },
188
- }
189
- stopDataBytes, _ := json.Marshal(stopData)
190
- c.Data(http.StatusOK, "application/json", []byte("data: "))
191
- c.Data(http.StatusOK, "application/json", stopDataBytes)
192
- c.Data(http.StatusOK, "application/json", []byte("\n\n"))
193
- flusher.Flush()
194
-
195
- c.Data(http.StatusOK, "application/json", []byte("data: [DONE]\n\n"))
196
- flusher.Flush()
197
- return
198
- }
199
  }
200
 
201
  var data DuckDuckGoResponse
@@ -211,10 +174,6 @@ func chatWithDuckDuckGo(c *gin.Context, messages []struct {
211
  response.Object = "chat.completion"
212
  response.Created = data.Created
213
  response.Model = data.Model
214
- nonStreamResponse.ID = data.ID
215
- nonStreamResponse.Object = "chat.completion"
216
- nonStreamResponse.Created = data.Created
217
- nonStreamResponse.Model = data.Model
218
  responseContent += data.Message
219
 
220
  if stream {
@@ -236,8 +195,21 @@ func chatWithDuckDuckGo(c *gin.Context, messages []struct {
236
  }
237
  }
238
 
239
- func stringPtr(s string) *string {
240
- return &s
 
 
 
 
 
 
 
 
 
 
 
 
 
241
  }
242
 
243
  func main() {
@@ -250,6 +222,13 @@ func main() {
250
  })
251
  })
252
 
 
 
 
 
 
 
 
253
  r.POST("/v1/chat/completions", func(c *gin.Context) {
254
  var req OpenAIRequest
255
  if err := c.ShouldBindJSON(&req); err != nil {
@@ -282,4 +261,4 @@ func main() {
282
  })
283
 
284
  r.Run(":3456")
285
- }
 
5
  "bytes"
6
  "encoding/json"
7
  "io"
8
+ "log"
9
  "net/http"
10
+ "time"
11
 
12
  "github.com/gin-gonic/gin"
13
  )
14
 
15
+ const (
16
+ statusURL = "https://duckduckgo.com/duckchat/v1/status"
17
+ chatURL = "https://duckduckgo.com/duckchat/v1/chat"
18
+ userAgent = "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:123.0) Gecko/20100101 Firefox/123.0"
19
+ )
20
+
21
  type OpenAIRequest struct {
22
  Model string `json:"model"`
23
  Messages []struct {
 
74
  Role string `json:"role"`
75
  Content string `json:"content"`
76
  }, stream bool) {
77
+ client := &http.Client{Timeout: 10 * time.Second}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
 
79
+ // Get vqd_4
80
  req, err := http.NewRequest("GET", statusURL, nil)
81
  if err != nil {
82
+ log.Println(err)
83
+ c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create request"})
84
  return
85
  }
 
86
  req.Header.Set("x-vqd-accept", "1")
87
+ setHeaders(req, userAgent)
 
 
88
 
89
+ resp, err := client.Do(req)
90
  if err != nil {
91
+ log.Println(err)
92
+ c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get vqd_4"})
93
  return
94
  }
95
  defer resp.Body.Close()
96
 
97
  vqd4 := resp.Header.Get("x-vqd-4")
98
 
99
+ // Send chat request
100
  payload := map[string]interface{}{
101
  "model": "gpt-3.5-turbo-0125",
102
  "messages": messages,
103
  }
 
104
  payloadBytes, err := json.Marshal(payload)
105
  if err != nil {
106
+ log.Println(err)
107
+ c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to marshal payload"})
108
  return
109
  }
110
 
111
  req, err = http.NewRequest("POST", chatURL, bytes.NewBuffer(payloadBytes))
112
  if err != nil {
113
+ log.Println(err)
114
+ c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create request"})
115
  return
116
  }
 
117
  req.Header.Set("x-vqd-4", vqd4)
118
+ setHeaders(req, userAgent)
 
 
119
 
120
+ resp, err = client.Do(req)
121
  if err != nil {
122
+ log.Println(err)
123
+ c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to send chat request"})
124
  return
125
  }
126
  defer resp.Body.Close()
127
 
128
+ // Process response
129
  reader := bufio.NewReader(resp.Body)
130
  c.Header("Content-Type", "text/event-stream")
131
  c.Header("Cache-Control", "no-cache")
 
135
  flusher, _ := c.Writer.(http.Flusher)
136
 
137
  var response OpenAIResponse
 
138
  response.Choices = make([]OpenAIChoice, 1)
 
139
 
140
  var responseContent string
141
 
 
153
  chunk := line[6:]
154
 
155
  if bytes.HasPrefix(chunk, []byte("[DONE]")) {
156
+ response.Choices[0].Delta.Content = responseContent
157
+ response.Choices[0].Delta.Role = "assistant"
158
+ response.Choices[0].FinishReason = new(string)
159
+ *response.Choices[0].FinishReason = "stop"
160
+ c.JSON(http.StatusOK, response)
161
+ return
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
162
  }
163
 
164
  var data DuckDuckGoResponse
 
174
  response.Object = "chat.completion"
175
  response.Created = data.Created
176
  response.Model = data.Model
 
 
 
 
177
  responseContent += data.Message
178
 
179
  if stream {
 
195
  }
196
  }
197
 
198
+ func setHeaders(req *http.Request, userAgent string) {
199
+ req.Header.Set("User-Agent", userAgent)
200
+ req.Header.Set("Accept", "text/event-stream")
201
+ req.Header.Set("Accept-Language", "de,en-US;q=0.7,en;q=0.3")
202
+ req.Header.Set("Accept-Encoding", "gzip, deflate, br")
203
+ req.Header.Set("Referer", "https://duckduckgo.com/")
204
+ req.Header.Set("Content-Type", "application/json")
205
+ req.Header.Set("Origin", "https://duckduckgo.com")
206
+ req.Header.Set("Connection", "keep-alive")
207
+ req.Header.Set("Cookie", "dcm=1")
208
+ req.Header.Set("Sec-Fetch-Dest", "empty")
209
+ req.Header.Set("Sec-Fetch-Mode", "cors")
210
+ req.Header.Set("Sec-Fetch-Site", "same-origin")
211
+ req.Header.Set("Pragma", "no-cache")
212
+ req.Header.Set("TE", "trailers")
213
  }
214
 
215
  func main() {
 
222
  })
223
  })
224
 
225
+ r.OPTIONS("/v1/chat/completions", func(c *gin.Context) {
226
+ c.Header("Access-Control-Allow-Origin", "*")
227
+ c.Header("Access-Control-Allow-Methods", "POST, OPTIONS")
228
+ c.Header("Access-Control-Allow-Headers", "Content-Type, Accept, Origin, X-Requested-With")
229
+ c.Status(http.StatusOK)
230
+ })
231
+
232
  r.POST("/v1/chat/completions", func(c *gin.Context) {
233
  var req OpenAIRequest
234
  if err := c.ShouldBindJSON(&req); err != nil {
 
261
  })
262
 
263
  r.Run(":3456")
264
+ }