package app import ( "context" "errors" "fmt" "github.com/go-redis/redis/v8" "heruvym/dal/minio" "heruvym/dal/mongo" "heruvym/internal/utils/middleware" "heruvym/router" "heruvym/service" "heruvym/tools" "net/http" "time" "github.com/skeris/appInit" tb "gopkg.in/tucnak/telebot.v2" "github.com/themakers/hlog" "go.uber.org/zap" ) type App struct { err chan error logger *zap.Logger } const ( ENV = "env" DEFAULT = "default" ) type Options struct { MongoURI string `env:"BB_MONGO_URI" default:"mongodb://localhost:27017"` NumberPortLocal string `env:"BB_PORT" default:"1488"` AccountAddress string `env:"BB_AccountAddress" default:":8931"` LoggerDevMode bool `env:"BB_IS_PROD" default:"false"` MinioEndpoint string `env:"BB_MINIO_EP" default:"minio:9001"` MinioAccessKey string `env:"BB_MINIO_AK" default:"minio"` MinioSecretKey string `env:"BB_MINIO_SK" default:"miniostorage"` MinioRegion string `env:"S3_REGION" default:""` MinioToken string `env:"BB_MINIO_TOKEN" default:""` MongoDbTable string `env:"DATABASE_TABLE" default:"profile"` MongoCollections string `env:"COLLECTION_NAME" default:"profile,role"` TgToken string `env:"TELEGRAM_TOKEN" default:"5851043588:AAGXhigZAaNV1--n-jfS8eBgM7iZ2IDm668"` RedisHost string `env:"REDIS_HOST" default:"localhost:6379"` RedisPassword string `env:"REDIS_PASSWORD" default:""` RedisDB uint64 `env:"REDIS_DB" default:"0"` TgChatID uint64 `env:"TELEGRAM_CHAT_ID" default:"1001344671794"` } var ( errInvalidOptions = errors.New("invalid options") ) var _ appInit.CommonApp = (*App)(nil) type InfoSvcStarted struct{} type InfoSvcReady struct{} type InfoSvcShutdown struct { Signal string } type ErrorStoring struct { Err error Uri string } type ErrorCanNotServe struct { Err error } var zapOptions = []zap.Option{ zap.AddCaller(), zap.AddCallerSkip(2), zap.AddStacktrace(zap.ErrorLevel), } func New(ctx context.Context, opts interface{}, ver appInit.Version) (appInit.CommonApp, error) { var ( err error zapLogger *zap.Logger errChan = make(chan error) options Options ok bool ) if options, ok = opts.(Options); !ok { return App{}, errInvalidOptions } if options.LoggerDevMode { zapLogger, err = zap.NewProduction(zapOptions...) if err != nil { return nil, err } } else { zapLogger, err = zap.NewDevelopment(zapOptions...) if err != nil { return nil, err } } zapLogger = zapLogger.With( zap.String("SvcCommit", ver.Commit), zap.String("SvcVersion", ver.Release), zap.String("SvcBuildTime", ver.BuildTime), ) logger := hlog.New(zapLogger) logger.Emit(InfoSvcStarted{}) database, err := mongo.New( ctx, options.MongoURI, "support", logger, ) if err != nil { return nil, err } miniostore, err := minio.New(ctx, logger, options.MinioEndpoint, options.MinioAccessKey, options.MinioSecretKey, options.MinioToken, options.MinioRegion, false) if err != nil { fmt.Println(err) return nil, err } redisClient := redis.NewClient(&redis.Options{ Addr: options.RedisHost, Password: options.RedisPassword, DB: int(options.RedisDB), }) var newBot *tb.Bot newBot, err = tb.NewBot(tb.Settings{ Token: options.TgToken, Verbose: false, ParseMode: tb.ModeHTML, Poller: &tb.LongPoller{ Timeout: time.Second, }, }) if err != nil { //logger.Emit(json.Token(err)) return nil, err } heruvym := service.New(miniostore, database, logger, newBot, -int64(options.TgChatID), redisClient) mux := router.NewRouter(map[string]http.HandlerFunc{ "/create": heruvym.CreateTicket, "/subscribe": tools.SseWrapper(heruvym.GetList), "/ticket": tools.SseWrapper(heruvym.Subscribe), "/send": tools.HandlerWrapper(heruvym.PutMessage), "/requestScreenshot": tools.HandlerWrapper(heruvym.RequestScreenshot), "/sendFiles": heruvym.PutFile, "/sendSC": heruvym.PutSC, "/getTickets": tools.HandlerWrapper(heruvym.GetTickets), "/getMessages": tools.HandlerWrapper(heruvym.GetMessages), "/pick": tools.HandlerWrapper(heruvym.Pick), "/delegate": tools.HandlerWrapper(heruvym.Delegate), "/vote": tools.HandlerWrapper(heruvym.Vote), "/close": tools.HandlerWrapper(heruvym.CloseTicket), "/shown": tools.HandlerWrapper(heruvym.SetShown), }) mw := middleware.NewMiddleware( logger, "*", nil, ) mux.Use( func(handler http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // w.Header().Set("Access-Control-Allow-Origin", r.Header["Origin"][0]) // w.Header().Set("Access-Control-Allow-Credentials", "true") // w.Header().Set("Access-Control-Allow-Headers", "content-type") // w.Header().Set("Access-Control-Expose-Headers", "*") if r.Method == http.MethodOptions { return } handler.ServeHTTP(w, r) }) }, mw.MiddlewareLogger, //mw.MiddlewareOriginAccess, mw.MiddlewareRecovery, mw.MiddlewareJwt, mw.MiddlewareGetJwt, //mw.MiddlewareJwtPlug, //mw.MiddlewareRoleAccess, mw.ExtractHostMiddleware, ) fmt.Println("mux") server := &http.Server{ Handler: mux, Addr: fmt.Sprintf(":%s", options.NumberPortLocal), } // Account Server accountService := service.NewAccount(database) accountServer := NewAccountHTTP(database, zapLogger) accountServer.Register(accountService.GetRoutes()...) go func() { defer func() { if err := server.Shutdown(ctx); err != nil { errChan <- err } if err := accountServer.Stop(); err != nil { errChan <- err } }() logger.Emit(InfoSvcStarted{}) tmplKey := "%s.key" tmplCrt := "%s.crt" tmplCrt = fmt.Sprintf(tmplCrt, "prod") tmplKey = fmt.Sprintf(tmplKey, "prod") fmt.Println("ISPROd", options.LoggerDevMode) if options.LoggerDevMode { if err := server.ListenAndServeTLS(tmplCrt, tmplKey); err != nil { logger.Emit(ErrorCanNotServe{ Err: err, }) errChan <- err } go func() { if err := accountServer.StartTLS(options.AccountAddress, tmplCrt, tmplKey); err != nil { logger.Emit(ErrorCanNotServe{Err: err}) errChan <- err } }() } else { fmt.Println("startserver" + options.NumberPortLocal) if err := server.ListenAndServe(); err != nil { errChan <- err } go func() { if err := accountServer.Start(options.AccountAddress); err != nil { logger.Emit(ErrorCanNotServe{Err: err}) errChan <- err } }() } }() return &App{ logger: zapLogger, err: errChan, }, nil } func (a App) GetLogger() *zap.Logger { return a.logger } func (a App) GetErr() chan error { return a.err }