| package job
|
|
|
| import (
|
| "encoding/json"
|
| "io/ioutil"
|
| "log"
|
| "os"
|
| "sync"
|
| "time"
|
|
|
| "pplx2api/config"
|
| "pplx2api/core"
|
| )
|
|
|
| const (
|
|
|
| ConfigFileName = "sessions.json"
|
| )
|
|
|
| var (
|
| sessionUpdaterInstance *SessionUpdater
|
| sessionUpdaterOnce sync.Once
|
| )
|
|
|
|
|
| type SessionConfig struct {
|
| Sessions []config.SessionInfo `json:"sessions"`
|
| }
|
|
|
|
|
| type SessionUpdater struct {
|
| interval time.Duration
|
| stopChan chan struct{}
|
| isRunning bool
|
| runningLock sync.Mutex
|
| configPath string
|
| }
|
|
|
|
|
|
|
| func GetSessionUpdater(interval time.Duration) *SessionUpdater {
|
| sessionUpdaterOnce.Do(func() {
|
|
|
| configPath := ConfigFileName
|
|
|
| sessionUpdaterInstance = &SessionUpdater{
|
| interval: interval,
|
| stopChan: make(chan struct{}),
|
| isRunning: false,
|
| configPath: configPath,
|
| }
|
|
|
| sessionUpdaterInstance.loadSessionsFromFile()
|
| })
|
| return sessionUpdaterInstance
|
| }
|
|
|
|
|
| func (su *SessionUpdater) loadSessionsFromFile() {
|
|
|
| if _, err := os.Stat(su.configPath); os.IsNotExist(err) {
|
| log.Println("No sessions config file found, will create on first update")
|
| return
|
| }
|
|
|
|
|
| data, err := ioutil.ReadFile(su.configPath)
|
| if err != nil {
|
| log.Printf("Failed to read sessions config file: %v", err)
|
| return
|
| }
|
|
|
|
|
| var sessionConfig SessionConfig
|
| if err := json.Unmarshal(data, &sessionConfig); err != nil {
|
| log.Printf("Failed to parse sessions config file: %v", err)
|
| return
|
| }
|
|
|
|
|
| config.ConfigInstance.RwMutex.Lock()
|
| config.ConfigInstance.Sessions = sessionConfig.Sessions
|
| config.ConfigInstance.RwMutex.Unlock()
|
|
|
| log.Printf("Loaded %d sessions from config file", len(sessionConfig.Sessions))
|
| }
|
|
|
|
|
| func (su *SessionUpdater) saveSessionsToFile() error {
|
|
|
| config.ConfigInstance.RwMutex.RLock()
|
| sessionsCopy := make([]config.SessionInfo, len(config.ConfigInstance.Sessions))
|
| copy(sessionsCopy, config.ConfigInstance.Sessions)
|
| config.ConfigInstance.RwMutex.RUnlock()
|
|
|
|
|
| sessionConfig := SessionConfig{
|
| Sessions: sessionsCopy,
|
| }
|
|
|
|
|
| data, err := json.MarshalIndent(sessionConfig, "", " ")
|
| if err != nil {
|
| return err
|
| }
|
|
|
|
|
| err = ioutil.WriteFile(su.configPath, data, 0644)
|
| if err != nil {
|
| return err
|
| }
|
|
|
| log.Printf("Saved %d sessions to sessions.json file", len(sessionsCopy))
|
| return nil
|
| }
|
|
|
|
|
| func (su *SessionUpdater) Start() {
|
| su.runningLock.Lock()
|
| defer su.runningLock.Unlock()
|
| if su.isRunning {
|
| log.Println("Session updater is already running")
|
| return
|
| }
|
| su.isRunning = true
|
| su.stopChan = make(chan struct{})
|
| go su.runUpdateLoop()
|
| log.Println("Session updater started with interval:", su.interval)
|
| }
|
|
|
|
|
| func (su *SessionUpdater) Stop() {
|
| su.runningLock.Lock()
|
| defer su.runningLock.Unlock()
|
| if !su.isRunning {
|
| log.Println("Session updater is not running")
|
| return
|
| }
|
| close(su.stopChan)
|
| su.isRunning = false
|
| log.Println("Session updater stopped")
|
| }
|
|
|
|
|
| func (su *SessionUpdater) runUpdateLoop() {
|
| ticker := time.NewTicker(su.interval)
|
| defer ticker.Stop()
|
|
|
|
|
| for {
|
| select {
|
| case <-ticker.C:
|
| su.updateAllSessions()
|
| case <-su.stopChan:
|
| log.Println("Update loop terminated")
|
| return
|
| }
|
| }
|
| }
|
|
|
|
|
| func (su *SessionUpdater) updateAllSessions() {
|
| log.Println("Starting session update for all sessions...")
|
|
|
| config.ConfigInstance.RwMutex.RLock()
|
| sessionsCopy := make([]config.SessionInfo, len(config.ConfigInstance.Sessions))
|
| copy(sessionsCopy, config.ConfigInstance.Sessions)
|
| proxy := config.ConfigInstance.Proxy
|
| config.ConfigInstance.RwMutex.RUnlock()
|
|
|
| if len(sessionsCopy) == 0 {
|
| log.Println("No sessions to update")
|
| return
|
| }
|
|
|
| updatedSessions := make([]config.SessionInfo, len(sessionsCopy))
|
| var wg sync.WaitGroup
|
|
|
| for i, session := range sessionsCopy {
|
| wg.Add(1)
|
| go func(index int, origSession config.SessionInfo) {
|
| defer wg.Done()
|
|
|
|
|
| client := core.NewClient(origSession.SessionKey, proxy, "claude-3-opus-20240229", false)
|
| newCookie, err := client.GetNewCookie()
|
| if err != nil {
|
| log.Printf("Failed to update session %d: %v", index, err)
|
|
|
| updatedSessions[index] = origSession
|
| return
|
| }
|
|
|
| updatedSessions[index] = config.SessionInfo{
|
| SessionKey: newCookie,
|
| }
|
| }(i, session)
|
| }
|
|
|
| wg.Wait()
|
|
|
| config.ConfigInstance.RwMutex.Lock()
|
| config.ConfigInstance.Sessions = updatedSessions
|
| config.ConfigInstance.RwMutex.Unlock()
|
| log.Printf("All %d sessions have been updated", len(updatedSessions))
|
|
|
|
|
| if err := su.saveSessionsToFile(); err != nil {
|
| log.Printf("Failed to save updated config: %v", err)
|
| }
|
| }
|
|
|