diff --git a/Dockerfile b/Dockerfile
index 889d8a92..5d768a79 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -7,4 +7,4 @@ RUN CGO_ENABLED=0 go build -o /app/fsb -ldflags="-w -s" ./cmd/fsb
FROM scratch
COPY --from=builder /app/fsb /app/fsb
EXPOSE ${PORT}
-ENTRYPOINT ["/app/fsb"]
\ No newline at end of file
+ENTRYPOINT ["/app/fsb", "run"]
\ No newline at end of file
diff --git a/README.md b/README.md
index 99693f4d..47978798 100644
--- a/README.md
+++ b/README.md
@@ -68,7 +68,7 @@
- Extract the zip file to a folder.
- Create an a file named `fsb.env` and add all the variables there (see `fsb.sample.env` file for reference).
- Give the executable file permission to execute using the command `chmod +x fsb` (Not required for windows).
-- Run the bot using `./fsb` command. ( `./fsb.exe` for windows)
+- Run the bot using `./fsb run` command. ( `./fsb.exe run` for windows)
@@ -124,7 +124,7 @@ chmod +x fsb
mv fsb.sample.env fsb.env
nano fsb.env
# (add your environment variables, see the next section for more info)
-./fsb
+./fsb run
```
and to stop the program,
@@ -142,7 +142,7 @@ go build ./cmd/fsb/
Rename-Item -LiteralPath ".\fsb.sample.env" -NewName ".\fsb.env"
notepad fsb.env
# (add your environment variables, see the next section for more info)
-.\fsb
+.\fsb run
```
and to stop the program,
diff --git a/cmd/fsb/main.go b/cmd/fsb/main.go
index dff81a40..2e9eaf4e 100644
--- a/cmd/fsb/main.go
+++ b/cmd/fsb/main.go
@@ -2,64 +2,35 @@ package main
import (
"EverythingSuckz/fsb/config"
- "EverythingSuckz/fsb/internal/bot"
- "EverythingSuckz/fsb/internal/cache"
- "EverythingSuckz/fsb/internal/routes"
- "EverythingSuckz/fsb/internal/types"
- "EverythingSuckz/fsb/internal/utils"
"fmt"
- "net/http"
- "time"
+ "os"
- "github.com/gin-gonic/gin"
- "go.uber.org/zap"
+ "github.com/spf13/cobra"
)
const versionString = "3.0.0-alpha1"
-var startTime time.Time = time.Now()
-
-func main() {
- utils.InitLogger()
- log := utils.Logger
- mainLogger := log.Named("Main")
- mainLogger.Info("Starting server")
- config.Load(log)
- router := getRouter(log)
-
- _, err := bot.StartClient(log)
- if err != nil {
- log.Info(err.Error())
- return
- }
- cache.InitCache(log)
- bot.StartWorkers(log)
- bot.StartUserBot(log)
- mainLogger.Info("Server started", zap.Int("port", config.ValueOf.Port))
- mainLogger.Info("File Stream Bot", zap.String("version", versionString))
- err = router.Run(fmt.Sprintf(":%d", config.ValueOf.Port))
- if err != nil {
- mainLogger.Sugar().Fatalln(err)
- }
+var rootCmd = &cobra.Command{
+ Use: "fsb [command]",
+ Short: "Telegram File Stream Bot",
+ Long: "Telegram Bot to generate direct streamable links for telegram media.",
+ Example: "fsb run --port 8080",
+ Version: versionString,
+ CompletionOptions: cobra.CompletionOptions{DisableDefaultCmd: true},
+ Run: func(cmd *cobra.Command, args []string) {
+ cmd.Help()
+ },
+}
+func init() {
+ config.SetFlagsFromConfig(runCmd)
+ rootCmd.AddCommand(runCmd)
+ rootCmd.SetVersionTemplate(fmt.Sprintf(`Telegram File Stream Bot version %s`, versionString))
}
-func getRouter(log *zap.Logger) *gin.Engine {
- if config.ValueOf.Dev {
- gin.SetMode(gin.DebugMode)
- } else {
- gin.SetMode(gin.ReleaseMode)
+func main() {
+ if err := rootCmd.Execute(); err != nil {
+ fmt.Println(err)
+ os.Exit(1)
}
- router := gin.Default()
- router.Use(gin.ErrorLogger())
- router.GET("/", func(ctx *gin.Context) {
- ctx.JSON(http.StatusOK, types.RootResponse{
- Message: "Server is running.",
- Ok: true,
- Uptime: utils.TimeFormat(uint64(time.Since(startTime).Seconds())),
- Version: versionString,
- })
- })
- routes.Load(log, router)
- return router
}
diff --git a/cmd/fsb/run.go b/cmd/fsb/run.go
new file mode 100644
index 00000000..b5655b5e
--- /dev/null
+++ b/cmd/fsb/run.go
@@ -0,0 +1,72 @@
+package main
+
+import (
+ "EverythingSuckz/fsb/config"
+ "EverythingSuckz/fsb/internal/bot"
+ "EverythingSuckz/fsb/internal/cache"
+ "EverythingSuckz/fsb/internal/routes"
+ "EverythingSuckz/fsb/internal/types"
+ "EverythingSuckz/fsb/internal/utils"
+ "fmt"
+ "net/http"
+ "time"
+
+ "github.com/spf13/cobra"
+
+ "github.com/gin-gonic/gin"
+ "go.uber.org/zap"
+)
+
+var runCmd = &cobra.Command{
+ Use: "run",
+ Short: "Run the bot with the given configuration.",
+ DisableSuggestions: false,
+ Run: runApp,
+}
+
+var startTime time.Time = time.Now()
+
+func runApp(cmd *cobra.Command, args []string) {
+ utils.InitLogger()
+ log := utils.Logger
+ mainLogger := log.Named("Main")
+ mainLogger.Info("Starting server")
+ config.Load(log, cmd)
+ router := getRouter(log)
+
+ _, err := bot.StartClient(log)
+ if err != nil {
+ log.Info(err.Error())
+ return
+ }
+ cache.InitCache(log)
+ bot.StartWorkers(log)
+ bot.StartUserBot(log)
+ mainLogger.Info("Server started", zap.Int("port", config.ValueOf.Port))
+ mainLogger.Info("File Stream Bot", zap.String("version", versionString))
+ err = router.Run(fmt.Sprintf(":%d", config.ValueOf.Port))
+ if err != nil {
+ mainLogger.Sugar().Fatalln(err)
+ }
+
+}
+
+func getRouter(log *zap.Logger) *gin.Engine {
+ if config.ValueOf.Dev {
+ gin.SetMode(gin.DebugMode)
+ } else {
+ gin.SetMode(gin.ReleaseMode)
+ }
+ router := gin.Default()
+ router.Use(gin.ErrorLogger())
+ router.GET("/", func(ctx *gin.Context) {
+ ctx.JSON(http.StatusOK, types.RootResponse{
+ Message: "Server is running.",
+ Ok: true,
+ Uptime: utils.TimeFormat(uint64(time.Since(startTime).Seconds())),
+ Version: versionString,
+ })
+ })
+ routes.Load(log, router)
+ return router
+}
diff --git a/config/config.go b/config/config.go
index 51845eb8..13688c25 100644
--- a/config/config.go
+++ b/config/config.go
@@ -10,6 +10,7 @@ import (
"github.com/joho/godotenv"
"github.com/kelseyhightower/envconfig"
+ "github.com/spf13/cobra"
"go.uber.org/zap"
)
@@ -31,7 +32,7 @@ type config struct {
var botTokenRegex = regexp.MustCompile(`MULTI\_TOKEN\d+=(.*)`)
-func (c *config) setupEnvVars(log *zap.Logger) {
+func (c *config) loadFromEnvFile(log *zap.Logger) {
envPath := filepath.Clean("fsb.env")
log.Sugar().Infof("Trying to load ENV vars from %s", envPath)
err := godotenv.Load(envPath)
@@ -45,7 +46,74 @@ func (c *config) setupEnvVars(log *zap.Logger) {
log.Fatal("Unknown error while parsing env file.", zap.Error(err))
}
}
- err = envconfig.Process("", c)
+}
+
+func SetFlagsFromConfig(cmd *cobra.Command) {
+ cmd.Flags().Int32("api-id", ValueOf.ApiID, "Telegram API ID")
+ cmd.Flags().String("api-hash", ValueOf.ApiHash, "Telegram API Hash")
+ cmd.Flags().String("bot-token", ValueOf.BotToken, "Telegram Bot Token")
+ cmd.Flags().Int64("log-channel", ValueOf.LogChannelID, "Telegram Log Channel ID")
+ cmd.Flags().Bool("dev", ValueOf.Dev, "Enable development mode")
+ cmd.Flags().IntP("port", "p", ValueOf.Port, "Server port")
+ cmd.Flags().String("host", ValueOf.Host, "Server host that will be included in links")
+ cmd.Flags().Int("hash-length", ValueOf.HashLength, "Hash length in links")
+ cmd.Flags().Bool("use-session-file", ValueOf.UseSessionFile, "Use session files")
+ cmd.Flags().String("user-session", ValueOf.UserSession, "Pyrogram user session")
+ cmd.Flags().String("multi-token-txt-file", "", "Multi token txt file (Not implemented)")
+}
+
+func (c *config) loadConfigFromArgs(log *zap.Logger, cmd *cobra.Command) {
+ apiID, _ := cmd.Flags().GetInt32("api-id")
+ if apiID != 0 {
+ os.Setenv("API_ID", strconv.Itoa(int(apiID)))
+ }
+ apiHash, _ := cmd.Flags().GetString("api-hash")
+ if apiHash != "" {
+ os.Setenv("API_HASH", apiHash)
+ }
+ botToken, _ := cmd.Flags().GetString("bot-token")
+ if botToken != "" {
+ os.Setenv("BOT_TOKEN", botToken)
+ }
+ logChannelID, _ := cmd.Flags().GetString("log-channel")
+ if logChannelID != "" {
+ os.Setenv("LOG_CHANNEL", logChannelID)
+ }
+ dev, _ := cmd.Flags().GetBool("dev")
+ if dev {
+ os.Setenv("DEV", strconv.FormatBool(dev))
+ }
+ port, _ := cmd.Flags().GetInt("port")
+ if port != 0 {
+ os.Setenv("PORT", strconv.Itoa(port))
+ }
+ host, _ := cmd.Flags().GetString("host")
+ if host != "" {
+ os.Setenv("HOST", host)
+ }
+ hashLength, _ := cmd.Flags().GetInt("hash-length")
+ if hashLength != 0 {
+ os.Setenv("HASH_LENGTH", strconv.Itoa(hashLength))
+ }
+ useSessionFile, _ := cmd.Flags().GetBool("use-session-file")
+ if useSessionFile {
+ os.Setenv("USE_SESSION_FILE", strconv.FormatBool(useSessionFile))
+ }
+ userSession, _ := cmd.Flags().GetString("user-session")
+ if userSession != "" {
+ os.Setenv("USER_SESSION", userSession)
+ }
+ multiTokens, _ := cmd.Flags().GetString("multi-token-txt-file")
+ if multiTokens != "" {
+ os.Setenv("MULTI_TOKEN_TXT_FILE", multiTokens)
+ // TODO: Add support for importing tokens from a separate file
+ }
+}
+
+func (c *config) setupEnvVars(log *zap.Logger, cmd *cobra.Command) {
+ c.loadFromEnvFile(log)
+ c.loadConfigFromArgs(log, cmd)
+ err := envconfig.Process("", c)
if err != nil {
log.Fatal("Error while parsing env variables", zap.Error(err))
}
@@ -58,10 +126,10 @@ func (c *config) setupEnvVars(log *zap.Logger) {
val.FieldByName("MultiTokens").Set(reflect.ValueOf(c.MultiTokens))
}
-func Load(log *zap.Logger) {
+func Load(log *zap.Logger, cmd *cobra.Command) {
log = log.Named("Config")
defer log.Info("Loaded config")
- ValueOf.setupEnvVars(log)
+ ValueOf.setupEnvVars(log, cmd)
ValueOf.LogChannelID = int64(stripInt(log, int(ValueOf.LogChannelID)))
if ValueOf.HashLength == 0 {
log.Sugar().Info("HASH_LENGTH can't be 0, defaulting to 6")
diff --git a/go.mod b/go.mod
index aaaa3fc5..77bf5869 100644
--- a/go.mod
+++ b/go.mod
@@ -9,6 +9,7 @@ require (
github.com/joho/godotenv v1.5.1
github.com/kelseyhightower/envconfig v1.4.0
github.com/quantumsheep/range-parser v1.1.0
+ github.com/spf13/cobra v1.8.0
)
require (
@@ -24,12 +25,14 @@ require (
github.com/google/uuid v1.4.0 // indirect
github.com/gotd/ige v0.2.2 // indirect
github.com/gotd/neo v0.1.5 // indirect
+ github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/klauspost/compress v1.17.4 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/segmentio/asm v1.2.0 // indirect
+ github.com/spf13/pflag v1.0.5 // indirect
go.opentelemetry.io/otel v1.21.0 // indirect
go.opentelemetry.io/otel/trace v1.21.0 // indirect
go.uber.org/atomic v1.11.0 // indirect
diff --git a/go.sum b/go.sum
index 65bdce58..cf0fb2a8 100644
--- a/go.sum
+++ b/go.sum
@@ -14,6 +14,7 @@ github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhD
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
github.com/coocood/freecache v1.2.4 h1:UdR6Yz/X1HW4fZOuH0Z94KwG851GWOSknua5VUbb/5M=
github.com/coocood/freecache v1.2.4/go.mod h1:RBUWa/Cy+OHdfTGFEhEuE1pMCMX51Ncizj7rthiQ3vk=
+github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -61,6 +62,8 @@ github.com/gotd/neo v0.1.5 h1:oj0iQfMbGClP8xI59x7fE/uHoTJD7NZH9oV1WNuPukQ=
github.com/gotd/neo v0.1.5/go.mod h1:9A2a4bn9zL6FADufBdt7tZt+WMhvZoc5gWXihOPoiBQ=
github.com/gotd/td v0.89.0 h1:qRWbTmPYk5y/u4gNAj9qIkLJlQgdMGr4HzW2ix1Q2hA=
github.com/gotd/td v0.89.0/go.mod h1:NgvwaHPW8rAHPGjaKSKzwSe+N2cUWTmfaDs8P6HPp/U=
+github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
+github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
@@ -99,8 +102,13 @@ github.com/quantumsheep/range-parser v1.1.0 h1:k4f1F58f8FF54FBYc9dYBRM+8JkAxFo11
github.com/quantumsheep/range-parser v1.1.0/go.mod h1:acv4Vt2PvpGvRsvGju7Gk2ahKluZJsIUNR69W53J22I=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
+github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
+github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
+github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
+github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
+github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=