package internal import ( "fmt" netHttp "net/http" "os" "os/exec" "time" // _ "net/http/pprof" // Register pprof "github.com/debridmediamanager/zurg/internal/config" "github.com/debridmediamanager/zurg/internal/handlers" "github.com/debridmediamanager/zurg/internal/torrent" "github.com/debridmediamanager/zurg/internal/universal" "github.com/debridmediamanager/zurg/internal/version" "github.com/debridmediamanager/zurg/pkg/http" "github.com/debridmediamanager/zurg/pkg/logutil" "github.com/debridmediamanager/zurg/pkg/premium" "github.com/debridmediamanager/zurg/pkg/realdebrid" "github.com/debridmediamanager/zurg/pkg/utils" "github.com/go-chi/chi/v5" "github.com/panjf2000/ants/v2" "go.uber.org/zap/zapcore" ) func MainApp(configPath string) { utils.EnsureDirExists("logs") // log files utils.EnsureDirExists("data") // cache files (info, bins, etc.) utils.EnsureDirExists("data/info") utils.EnsureDirExists("dump") // "zurgtorrent" files log := logutil.NewLogger("logs/zurg.log") zurglog := log.Named("zurg") // logger for this main function zurglog.Debugf("PID: %d", os.Getpid()) zurglog.Infof("Version: %s", version.GetVersion()) zurglog.Infof("GitCommit: %s", version.GetGitCommit()) zurglog.Infof("BuiltAt: %s", version.GetBuiltAt()) if log.Level() == zapcore.DebugLevel { zurglog.Infof("Debug logging is enabled; if you are not debugging please set LOG_LEVEL=INFO in your system environment") } config, configErr := config.LoadZurgConfig(configPath, log.Named("config")) if configErr != nil { zurglog.Errorf("Config failed to load: %v", configErr) os.Exit(1) } var proxyURL string if config.GetProxy() != "" { proxyURL = config.GetProxy() zurglog.Infof("Using proxy: %s", proxyURL) } else { proxyURL = os.Getenv("PROXY") } repoClient4 := http.NewHTTPClient("", 0, 1, false, []string{}, proxyURL, nil, log.Named("network_test")) repoClient6 := http.NewHTTPClient("", 0, 1, true, []string{}, proxyURL, nil, log.Named("network_test")) repo := http.NewIPRepository(repoClient4, repoClient6, "", log.Named("network_test")) var hosts []string repo.NetworkTest(false, config.ShouldCacheNetworkTestResults()) hosts = repo.GetHosts(config.GetNumberOfHosts(), config.ShouldForceIPv6()) if len(hosts) == 0 { zurglog.Errorf("No reachable hosts found. Trying again.") for { repo.NetworkTest(true, config.ShouldCacheNetworkTestResults()) hosts = repo.GetHosts(config.GetNumberOfHosts(), config.ShouldForceIPv6()) if len(hosts) == 0 { zurglog.Errorf("No reachable hosts found. Trying again in 5 minutes.") time.Sleep(5 * time.Minute) continue } zurglog.Debugf("Reachable hosts (%d): %v", len(hosts), hosts) break } } rateLimiter := http.NewRateLimiter(config.GetAPIRateLimitPerMinute()) apiClient := http.NewHTTPClient( config.GetToken(), config.GetRetriesUntilFailed(), // default retries = 2 config.GetApiTimeoutSecs(), // default api timeout = 60 false, // no need for ipv6 support []string{}, // no optimal hosts needed proxyURL, rateLimiter, log.Named("api_client"), ) unrestrictClient := http.NewHTTPClient( "", config.GetRetriesUntilFailed(), // default retries = 2 config.GetDownloadTimeoutSecs(), // default download timeout = 10 false, // no need for ipv6 support []string{}, // no optimal hosts needed proxyURL, rateLimiter, log.Named("unrestrict_client"), ) downloadClient := http.NewHTTPClient( "", config.GetRetriesUntilFailed(), config.GetDownloadTimeoutSecs(), config.ShouldForceIPv6(), hosts, proxyURL, nil, log.Named("download_client"), ) workerCount := config.GetNumberOfWorkers() if workerCount < 20 { workerCount = 20 } workerPool, err := ants.NewPool(workerCount) if err != nil { zurglog.Errorf("Failed to create worker pool: %v", err) os.Exit(1) } defer workerPool.Release() torrentsRateLimiter := http.NewRateLimiter(config.GetTorrentsRateLimitPerMinute()) rd := realdebrid.NewRealDebrid( apiClient, unrestrictClient, downloadClient, workerPool, torrentsRateLimiter, config, log.Named("realdebrid"), ) rd.MonitorExpiredTokens() premium.MonitorPremiumStatus( workerPool, rd, zurglog, ) hasFFprobe := true _, err = exec.LookPath("ffprobe") if err != nil { hasFFprobe = false zurglog.Warn("ffprobe not found in PATH (do you have ffmpeg installed?), you won't be able to perform media analysis") } torrentMgr := torrent.NewTorrentManager( config, rd, workerPool, hasFFprobe, log.Named("manager"), log.Named("repair"), ) downloader := universal.NewDownloader(rd, workerPool) downloader.StartResetBandwidthCountersJob() router := chi.NewRouter() handlers.AttachHandlers( router, downloader, torrentMgr, config, rd, workerPool, hosts, log.Named("router"), ) //// pprof // workerPool.Submit(func() { // if err := netHttp.ListenAndServe(":6060", nil); err != nil && err != netHttp.ErrServerClosed { // zurglog.Errorf("Failed to start pprof: %v", err) // os.Exit(1) // } // }) addr := fmt.Sprintf("%s:%s", config.GetHost(), config.GetPort()) zurglog.Infof("Starting server on %s", addr) if err := netHttp.ListenAndServe(addr, router); err != nil && err != netHttp.ErrServerClosed { zurglog.Errorf("Failed to start server: %v", err) os.Exit(1) } }