123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199 |
- package backend
- import (
- "context"
- "fmt"
- "github.com/ChineseSubFinder/ChineseSubFinder/pkg/logic/pre_job"
- "io/ioutil"
- "net/http"
- "sync"
- "time"
- "github.com/ChineseSubFinder/ChineseSubFinder/pkg"
- "github.com/ChineseSubFinder/ChineseSubFinder/pkg/local_http_proxy_server"
- "github.com/ChineseSubFinder/ChineseSubFinder/pkg/settings"
- "github.com/ChineseSubFinder/ChineseSubFinder/frontend/dist"
- "github.com/gin-contrib/cors"
- "github.com/gin-gonic/gin"
- "github.com/sirupsen/logrus"
- "github.com/ChineseSubFinder/ChineseSubFinder/pkg/logic/cron_helper"
- )
- type BackEnd struct {
- logger *logrus.Logger
- cronHelper *cron_helper.CronHelper
- httpPort int
- running bool
- srv *http.Server
- locker sync.Mutex
- restartSignal chan interface{}
- preJob *pre_job.PreJob
- }
- func NewBackEnd(
- logger *logrus.Logger,
- cronHelper *cron_helper.CronHelper,
- httpPort int,
- restartSignal chan interface{}) *BackEnd {
- return &BackEnd{
- logger: logger,
- cronHelper: cronHelper,
- httpPort: httpPort,
- restartSignal: restartSignal,
- preJob: pre_job.NewPreJob(logger),
- }
- }
- func (b *BackEnd) start() {
- defer b.locker.Unlock()
- b.locker.Lock()
- if b.running == true {
- b.logger.Debugln("Http Server is already running")
- return
- }
- b.running = true
- // ----------------------------------------
- // 设置代理
- err := local_http_proxy_server.SetProxyInfo(settings.Get().AdvancedSettings.ProxySettings.GetInfos())
- if err != nil {
- b.logger.Errorln("Set Local Http Proxy Server Error:", err)
- return
- }
- // -----------------------------------------
- // 设置跨域
- gin.SetMode(gin.ReleaseMode)
- gin.DefaultWriter = ioutil.Discard
- engine := gin.Default()
- // 默认所有都通过
- engine.Use(cors.Default())
- // 初始化路由
- cbBase, v1Router := InitRouter(engine, b.cronHelper, b.restartSignal, b.preJob)
- // -----------------------------------------
- // 静态文件服务器
- engine.GET("/", func(c *gin.Context) {
- c.Header("content-type", "text/html;charset=utf-8")
- c.String(http.StatusOK, string(dist.SpaIndexHtml))
- })
- engine.StaticFS(dist.SpaFolderJS, dist.Assets(dist.SpaFolderName+dist.SpaFolderJS, dist.SpaJS))
- engine.StaticFS(dist.SpaFolderCSS, dist.Assets(dist.SpaFolderName+dist.SpaFolderCSS, dist.SpaCSS))
- engine.StaticFS(dist.SpaFolderFonts, dist.Assets(dist.SpaFolderName+dist.SpaFolderFonts, dist.SpaFonts))
- engine.StaticFS(dist.SpaFolderIcons, dist.Assets(dist.SpaFolderName+dist.SpaFolderIcons, dist.SpaIcons))
- engine.StaticFS(dist.SpaFolderImages, dist.Assets(dist.SpaFolderName+dist.SpaFolderImages, dist.SpaImages))
- // -----------------------------------------
- // 用于预览视频和字幕的静态文件服务
- previewCacheFolder, err := pkg.GetVideoAndSubPreviewCacheFolder()
- if err != nil {
- b.logger.Errorln("GetVideoAndSubPreviewCacheFolder Error:", err)
- return
- }
- engine.StaticFS("/static/preview", http.Dir(previewCacheFolder))
- // -----------------------------------------
- // api 服务
- engine.Any("/api", func(c *gin.Context) {
- c.Redirect(http.StatusMovedPermanently, "/")
- })
- // listen and serve on 0.0.0.0:8080(default)
- b.srv = &http.Server{
- Addr: fmt.Sprintf(":%d", b.httpPort),
- Handler: engine,
- }
- go func() {
- b.doPreJob()
- b.doCornJob()
- }()
- // 启动 http server
- go func() {
- b.logger.Infoln("Try Start Http Server At Port", b.httpPort)
- if err := b.srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
- b.logger.Errorln("Start Server Error:", err)
- }
- defer func() {
- cbBase.Close()
- v1Router.Close()
- }()
- }()
- }
- func (b *BackEnd) Restart() {
- stopFunc := func() {
- b.locker.Lock()
- defer func() {
- b.locker.Unlock()
- }()
- if b.running == false {
- b.logger.Debugln("Http Server is not running")
- return
- }
- b.running = false
- exitOk := make(chan interface{}, 1)
- defer close(exitOk)
- ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
- defer cancel()
- go func() {
- if err := b.srv.Shutdown(ctx); err != nil {
- b.logger.Errorln("Http Server Shutdown:", err)
- }
- exitOk <- true
- }()
- select {
- case <-ctx.Done():
- b.logger.Warningln("Http Server Shutdown timeout of 5 seconds.")
- case <-exitOk:
- b.logger.Infoln("Http Server Shutdown Successfully")
- }
- b.logger.Infoln("Http Server Shutdown Done.")
- }
- for {
- select {
- case <-b.restartSignal:
- {
- stopFunc()
- b.start()
- }
- }
- }
- }
- // doPreJob 前置的任务,热修复、字幕修改文件名格式、提前下载好浏览器
- func (b *BackEnd) doPreJob() {
- // 启动程序只会执行一次,用 Once 控制
- // 前置的任务,热修复、字幕修改文件名格式、提前下载好浏览器
- if settings.Get().SpeedDevMode == true {
- return
- }
- if pkg.LiteMode() == false {
- return
- }
- // 不启用 Chrome 相关操作
- err := b.preJob.HotFix().ChangeSubNameFormat().Wait()
- if err != nil {
- b.logger.Errorln("pre_job", err)
- }
- }
- // doCornJob 定时任务
- func (b *BackEnd) doCornJob() {
- // 需要使用 go 来执行,因为这个函数是阻塞的
- // 启动定时任务
- if settings.Get().UserInfo.Username == "" || settings.Get().UserInfo.Password == "" {
- // 如果没有完成,那么就不开启
- b.logger.Infoln("Need do Setup")
- } else {
- // 是否完成了 Setup,如果完成了,那么就开启第一次的扫描
- go func() {
- b.logger.Infoln("Setup is Done")
- b.cronHelper.Start(settings.Get().CommonSettings.RunScanAtStartUp)
- }()
- }
- }
|