| | package service
|
| |
|
| | import (
|
| | "bytes"
|
| | "encoding/json"
|
| | "io"
|
| | "net/http"
|
| | "opus-api/internal/converter"
|
| | "opus-api/internal/model"
|
| | "opus-api/internal/types"
|
| | "time"
|
| |
|
| | "gorm.io/gorm"
|
| | )
|
| |
|
| |
|
| | type CookieValidator struct {
|
| | service *CookieService
|
| | }
|
| |
|
| |
|
| | func NewCookieValidator(service *CookieService) *CookieValidator {
|
| | return &CookieValidator{service: service}
|
| | }
|
| |
|
| |
|
| | func (v *CookieValidator) ValidateCookie(cookie *model.MorphCookie) bool {
|
| | result := v.testCookie(cookie)
|
| |
|
| | db := v.service.GetDB()
|
| | if result {
|
| | db.Model(cookie).Updates(map[string]interface{}{
|
| | "is_valid": true,
|
| | "last_validated": time.Now(),
|
| | "error_count": 0,
|
| | })
|
| | } else {
|
| | db.Model(cookie).Updates(map[string]interface{}{
|
| | "is_valid": false,
|
| | "last_validated": time.Now(),
|
| | "error_count": gorm.Expr("error_count + ?", 1),
|
| | })
|
| | }
|
| |
|
| | return result
|
| | }
|
| |
|
| |
|
| | func (v *CookieValidator) ValidateAllCookies(userID uint) map[uint]bool {
|
| | cookies, err := v.service.ListCookies(userID)
|
| | if err != nil {
|
| | return nil
|
| | }
|
| |
|
| | results := make(map[uint]bool)
|
| | for _, cookie := range cookies {
|
| | results[cookie.ID] = v.ValidateCookie(&cookie)
|
| | }
|
| |
|
| | return results
|
| | }
|
| |
|
| |
|
| | func (v *CookieValidator) testCookie(cookie *model.MorphCookie) bool {
|
| | client := &http.Client{
|
| | Timeout: 30 * time.Second,
|
| | }
|
| |
|
| |
|
| | claudeReq := types.ClaudeRequest{
|
| | Model: types.DefaultModel,
|
| | MaxTokens: 1024,
|
| | Messages: []types.ClaudeMessage{
|
| | {
|
| | Role: "user",
|
| | Content: "Hello!",
|
| | },
|
| | },
|
| | }
|
| |
|
| |
|
| | morphReq := converter.ClaudeToMorph(claudeReq)
|
| |
|
| | reqBody, _ := json.Marshal(morphReq)
|
| | req, err := http.NewRequest("POST", types.MorphAPIURL, bytes.NewReader(reqBody))
|
| | if err != nil {
|
| | return false
|
| | }
|
| |
|
| |
|
| | for key, value := range types.MorphHeaders {
|
| | req.Header.Set(key, value)
|
| | }
|
| |
|
| | req.Header.Set("cookie", cookie.APIKey)
|
| |
|
| | resp, err := client.Do(req)
|
| | if err != nil {
|
| | return false
|
| | }
|
| | defer resp.Body.Close()
|
| |
|
| |
|
| |
|
| | if resp.StatusCode == http.StatusUnauthorized || resp.StatusCode == http.StatusForbidden {
|
| | return false
|
| | }
|
| |
|
| |
|
| | body, _ := io.ReadAll(resp.Body)
|
| |
|
| |
|
| | bodyStr := string(body)
|
| |
|
| |
|
| | if !containsPrefix(bodyStr, "data:") {
|
| | return false
|
| | }
|
| |
|
| | return true
|
| | }
|
| |
|
| |
|
| | func containsPrefix(s, prefix string) bool {
|
| |
|
| | start := 0
|
| | for start < len(s) && (s[start] == ' ' || s[start] == '\t' || s[start] == '\n' || s[start] == '\r') {
|
| | start++
|
| | }
|
| |
|
| | if start >= len(s) {
|
| | return false
|
| | }
|
| |
|
| | return len(s[start:]) >= len(prefix) && s[start:start+len(prefix)] == prefix
|
| | }
|
| |
|
| |
|
| | func (v *CookieValidator) validateCookieQuiet(cookie *model.MorphCookie) bool {
|
| | return v.testCookie(cookie)
|
| | } |