REPOSITORY / ScuroNeko/Laniakea
Compare commits
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c59dd1fe8e
|
||
|
|
2fc171d9a3
|
@@ -2,11 +2,11 @@ package laniakea
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
|
||||||
|
|
||||||
"git.nix13.pw/scuroneko/extypes"
|
"git.nix13.pw/scuroneko/extypes"
|
||||||
"git.nix13.pw/scuroneko/laniakea/tgapi"
|
"git.nix13.pw/scuroneko/laniakea/tgapi"
|
||||||
@@ -174,7 +174,7 @@ func NewBot[T any](opts *BotOpts) *Bot[T] {
|
|||||||
return bot
|
return bot
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close gracefully shuts down the bot.
|
// Close gracefully shuts down bot-owned resources.
|
||||||
//
|
//
|
||||||
// Closes:
|
// Closes:
|
||||||
// - Uploader (waits for pending uploads)
|
// - Uploader (waits for pending uploads)
|
||||||
@@ -182,36 +182,31 @@ func NewBot[T any](opts *BotOpts) *Bot[T] {
|
|||||||
// - RequestLogger (if enabled)
|
// - RequestLogger (if enabled)
|
||||||
// - Main logger
|
// - Main logger
|
||||||
//
|
//
|
||||||
// Returns the first error encountered, if any.
|
// RunWithContext does not call Close automatically. The caller is responsible
|
||||||
|
// for invoking Close after RunWithContext returns to release these resources.
|
||||||
|
//
|
||||||
|
// Returns a joined error containing all shutdown failures, if any.
|
||||||
func (bot *Bot[T]) Close() error {
|
func (bot *Bot[T]) Close() error {
|
||||||
var firstErr error
|
var e []error
|
||||||
|
|
||||||
if err := bot.uploader.Close(); err != nil {
|
if err := bot.uploader.Close(); err != nil {
|
||||||
bot.logger.Errorln(err)
|
bot.logger.Errorln(err)
|
||||||
if firstErr == nil {
|
e = append(e, err)
|
||||||
firstErr = err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if err := bot.api.CloseApi(); err != nil {
|
if err := bot.api.CloseApi(); err != nil {
|
||||||
bot.logger.Errorln(err)
|
bot.logger.Errorln(err)
|
||||||
if firstErr == nil {
|
e = append(e, err)
|
||||||
firstErr = err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if bot.RequestLogger != nil {
|
if bot.RequestLogger != nil {
|
||||||
if err := bot.RequestLogger.Close(); err != nil {
|
if err := bot.RequestLogger.Close(); err != nil {
|
||||||
bot.logger.Errorln(err)
|
bot.logger.Errorln(err)
|
||||||
if firstErr == nil {
|
e = append(e, err)
|
||||||
firstErr = err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := bot.logger.Close(); err != nil {
|
if err := bot.logger.Close(); err != nil {
|
||||||
if firstErr == nil {
|
e = append(e, err)
|
||||||
firstErr = err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return firstErr
|
return errors.Join(e...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// initLoggers configures the main and optional request loggers.
|
// initLoggers configures the main and optional request loggers.
|
||||||
@@ -466,7 +461,10 @@ func (bot *Bot[T]) AddDatabaseLoggerWriter(writer DbLogger[T]) *Bot[T] {
|
|||||||
// The context controls graceful shutdown. When canceled, the bot:
|
// The context controls graceful shutdown. When canceled, the bot:
|
||||||
// - Stops polling for new updates
|
// - Stops polling for new updates
|
||||||
// - Finishes processing currently queued updates
|
// - Finishes processing currently queued updates
|
||||||
// - Closes all resources (API, uploader, loggers)
|
// - Waits for registered runners to exit
|
||||||
|
//
|
||||||
|
// RunWithContext does not close API, uploader, or logger resources on return.
|
||||||
|
// The caller must invoke Close after RunWithContext finishes.
|
||||||
//
|
//
|
||||||
// Example:
|
// Example:
|
||||||
//
|
//
|
||||||
@@ -474,13 +472,8 @@ func (bot *Bot[T]) AddDatabaseLoggerWriter(writer DbLogger[T]) *Bot[T] {
|
|||||||
// go bot.RunWithContext(ctx)
|
// go bot.RunWithContext(ctx)
|
||||||
// // ... later ...
|
// // ... later ...
|
||||||
// cancel() // triggers graceful shutdown
|
// cancel() // triggers graceful shutdown
|
||||||
|
// _ = bot.Close()
|
||||||
func (bot *Bot[T]) RunWithContext(ctx context.Context) {
|
func (bot *Bot[T]) RunWithContext(ctx context.Context) {
|
||||||
defer func() {
|
|
||||||
if err := bot.Close(); err != nil {
|
|
||||||
bot.logger.Errorln(err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
if len(bot.prefixes) == 0 {
|
if len(bot.prefixes) == 0 {
|
||||||
bot.logger.Fatalln("no prefixes defined")
|
bot.logger.Fatalln("no prefixes defined")
|
||||||
return
|
return
|
||||||
@@ -508,15 +501,17 @@ func (bot *Bot[T]) RunWithContext(ctx context.Context) {
|
|||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
updates, err := bot.Updates()
|
updates, err := bot.Updates(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if errors.Is(err, context.Canceled) {
|
||||||
|
return
|
||||||
|
}
|
||||||
bot.logger.Errorln("failed to fetch updates:", err)
|
bot.logger.Errorln("failed to fetch updates:", err)
|
||||||
time.Sleep(2 * time.Second) // exponential backoff
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, u := range updates {
|
for _, update := range updates {
|
||||||
u := u // copy loop variable to avoid race condition
|
u := update // copy loop variable to avoid race condition
|
||||||
select {
|
select {
|
||||||
case bot.updateQueue <- &u:
|
case bot.updateQueue <- &u:
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
|
|||||||
+8
-6
@@ -1,6 +1,7 @@
|
|||||||
package laniakea
|
package laniakea
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"git.nix13.pw/scuroneko/laniakea/tgapi"
|
"git.nix13.pw/scuroneko/laniakea/tgapi"
|
||||||
@@ -12,7 +13,7 @@ import (
|
|||||||
// through AllowedUpdates and includes optional request logging.
|
// through AllowedUpdates and includes optional request logging.
|
||||||
//
|
//
|
||||||
// Parameters:
|
// Parameters:
|
||||||
// - None (uses bot's internal state for offset and allowed updates)
|
// - ctx: request context used to cancel the in-flight long polling request
|
||||||
//
|
//
|
||||||
// Returns:
|
// Returns:
|
||||||
// - []tgapi.Update: slice of received updates (empty if none available)
|
// - []tgapi.Update: slice of received updates (empty if none available)
|
||||||
@@ -26,19 +27,20 @@ import (
|
|||||||
// 5. Automatically updates the offset to the last received update ID + 1
|
// 5. Automatically updates the offset to the last received update ID + 1
|
||||||
// 6. Returns all received updates (empty slice if none)
|
// 6. Returns all received updates (empty slice if none)
|
||||||
//
|
//
|
||||||
// Note: This is a blocking call that waits up to 30 seconds for new updates.
|
// Note: This is a blocking call that waits up to 30 seconds for new updates,
|
||||||
// For non-blocking behavior, consider using webhooks instead.
|
// unless ctx is canceled earlier. For non-blocking behavior, consider using
|
||||||
|
// webhooks instead.
|
||||||
//
|
//
|
||||||
// Example:
|
// Example:
|
||||||
//
|
//
|
||||||
// updates, err := bot.Updates()
|
// updates, err := bot.Updates(ctx)
|
||||||
// if err != nil {
|
// if err != nil {
|
||||||
// log.Fatal(err)
|
// log.Fatal(err)
|
||||||
// }
|
// }
|
||||||
// for _, update := range updates {
|
// for _, update := range updates {
|
||||||
// // process update
|
// // process update
|
||||||
// }
|
// }
|
||||||
func (bot *Bot[T]) Updates() ([]tgapi.Update, error) {
|
func (bot *Bot[T]) Updates(ctx context.Context) ([]tgapi.Update, error) {
|
||||||
offset := bot.GetUpdateOffset()
|
offset := bot.GetUpdateOffset()
|
||||||
params := tgapi.UpdateParams{
|
params := tgapi.UpdateParams{
|
||||||
Offset: Ptr(offset),
|
Offset: Ptr(offset),
|
||||||
@@ -46,7 +48,7 @@ func (bot *Bot[T]) Updates() ([]tgapi.Update, error) {
|
|||||||
AllowedUpdates: bot.GetUpdateTypes(),
|
AllowedUpdates: bot.GetUpdateTypes(),
|
||||||
}
|
}
|
||||||
|
|
||||||
updates, err := bot.api.GetUpdates(params)
|
updates, err := bot.api.GetUpdatesWithContext(ctx, params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,6 +48,11 @@ func (api *API) GetUpdates(params UpdateParams) ([]Update, error) {
|
|||||||
return req.Do(api)
|
return req.Do(api)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (api *API) GetUpdatesWithContext(ctx context.Context, params UpdateParams) ([]Update, error) {
|
||||||
|
req := NewRequest[[]Update]("getUpdates", params)
|
||||||
|
return req.DoWithContext(ctx, api)
|
||||||
|
}
|
||||||
|
|
||||||
// SetWebhookP holds parameters for the setWebhook method.
|
// SetWebhookP holds parameters for the setWebhook method.
|
||||||
// See https://core.telegram.org/bots/api#setwebhook
|
// See https://core.telegram.org/bots/api#setwebhook
|
||||||
type SetWebhookP struct {
|
type SetWebhookP struct {
|
||||||
|
|||||||
+2
-2
@@ -1,9 +1,9 @@
|
|||||||
package utils
|
package utils
|
||||||
|
|
||||||
const (
|
const (
|
||||||
VersionString = "1.0.0-beta.22"
|
VersionString = "1.0.0-rc.3"
|
||||||
VersionMajor = 1
|
VersionMajor = 1
|
||||||
VersionMinor = 0
|
VersionMinor = 0
|
||||||
VersionPatch = 0
|
VersionPatch = 0
|
||||||
VersionBeta = 22
|
VersionBeta = 3
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user