Files
trbot/main.go
Hubert Chen 94c249846b add handler_params for each update type
packages:
    rename `errt` to `err_template`
    rename `multe` to `flat_err`
    rename `handler_structs` to `handler_params` with changes
logger:
    move some fields to top logger
    create sub logger when need
handler and sub-handler:
    create sub params when need
plugin_utils:
    rename `CustomSymbolCommand` to `FullCommand`
    rename `SlashSymbolCommand` to `SlashCommand`
2025-07-06 01:51:47 +08:00

107 lines
3.3 KiB
Go

package main
import (
"context"
"net/http"
"os"
"os/signal"
"time"
"trbot/database"
"trbot/utils"
"trbot/utils/configs"
"trbot/utils/consts"
"trbot/utils/internal_plugin"
"trbot/utils/signals"
"github.com/go-telegram/bot"
"github.com/rs/zerolog"
"github.com/rs/zerolog/pkgerrors"
)
func main() {
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
defer cancel()
zerolog.ErrorStackMarshaler = pkgerrors.MarshalStack // set stack trace func
logger := zerolog.New(zerolog.ConsoleWriter{Out: os.Stdout}).With().Timestamp().Logger()
ctx = logger.WithContext(ctx) // attach logger into ctx
// read bot configs
err := configs.InitBot(ctx)
if err != nil { logger.Fatal().Err(err).Msg("Failed to read bot configs") }
// writer log to a file or only display on console
if configs.IsUseMultiLogWriter(&logger) { ctx = logger.WithContext(ctx) } // re-attach logger into ctx
configs.CheckConfig(ctx) // check and auto fill some config
configs.ShowConst(ctx) // show build info
thebot, err := bot.New(configs.BotConfig.BotToken, []bot.Option{
bot.WithDefaultHandler(defaultHandler),
bot.WithAllowedUpdates(configs.BotConfig.AllowedUpdates),
}...)
if err != nil { logger.Fatal().Err(err).Msg("Failed to initialize bot") }
consts.BotMe, err = thebot.GetMe(ctx)
if err != nil { logger.Fatal().Err(err).Msg("Failed to get bot info") }
logger.Info().
Dict(utils.GetUserDict(consts.BotMe)).
Msg("Bot initialized")
database.InitAndListDatabases(ctx)
// set log level after bot initialized
zerolog.SetGlobalLevel(configs.BotConfig.LevelForZeroLog(false))
// start handler custom signals
go signals.SignalsHandler(ctx)
// register plugin (plugin use `init()` first, then plugin use `InitPlugins` second, and internal is the last)
internal_plugin.Register(ctx)
// Select mode by Webhook config
if configs.IsUsingWebhook(ctx) /* Webhook */ {
if configs.SetUpWebhook(ctx, thebot, &bot.SetWebhookParams{
URL: configs.BotConfig.WebhookURL,
AllowedUpdates: configs.BotConfig.AllowedUpdates,
}) {
logger.Info().
Str("listenAddress", consts.WebhookListenPort).
Msg("Working at Webhook Mode")
go thebot.StartWebhook(ctx)
err := http.ListenAndServe(consts.WebhookListenPort, thebot.WebhookHandler())
if err != nil {
logger.Fatal().
Err(err).
Msg("Webhook server failed")
}
} else {
logger.Fatal().
Str("webhookURL", configs.BotConfig.WebhookURL).
Msg("Failed to setup Webhook")
}
} else /* getUpdate, aka Long Polling */ {
// remove Webhook URL befor using getUpdate https://core.telegram.org/bots/api#getupdates
if configs.CleanRemoteWebhookURL(ctx, thebot) {
logger.Info().
Msg("Working at Long Polling Mode")
logger.Debug().
Msgf("visit https://api.telegram.org/bot%s/getWebhookInfo to check infos", configs.BotConfig.BotToken)
thebot.Start(ctx)
} else {
logger.Fatal().
Msg("Failed to remove Webhook URL")
}
}
// A loop wait for getUpdate mode, this program will exit in `utils\signals\signals.go`.
// This loop will only run when the exit signal is received in getUpdate mode.
// Webhook mode won't reach here, http.ListenAndServe() will keep program running until exit.
// They use the same code to exit, this loop is to give some time to save the database when receive exit signal.
for {
time.Sleep(5 * time.Second)
logger.Info().Msg("still waiting...")
}
}