From e0e41e40b510f99668930fce765069145bcddd32 Mon Sep 17 00:00:00 2001 From: AmarnathCJD Date: Sun, 1 Dec 2024 15:41:24 +0530 Subject: [PATCH] fix-up some bugs, add support to name diffrent sessions, add filter support for editMessage and callbackQuery, customisable logger and cache now, v1.4.5 --- internal/utils/logging.go | 5 +++ telegram/cache.go | 59 ++++++++++++++++++++++-------- telegram/client.go | 21 ++++++++--- telegram/const.go | 2 +- telegram/updates.go | 75 +++++++++++++++++++++++++++++++-------- telegram/utils.go | 12 +++++++ 6 files changed, 138 insertions(+), 36 deletions(-) diff --git a/internal/utils/logging.go b/internal/utils/logging.go index f80ce672..87a346cb 100755 --- a/internal/utils/logging.go +++ b/internal/utils/logging.go @@ -58,6 +58,11 @@ func (l *Logger) Color() bool { return !l.nocolor } +func (l *Logger) SetPrefix(prefix string) *Logger { + l.Prefix = prefix + return l +} + func (l *Logger) colorize(color []byte, s string) string { if l.nocolor { return s diff --git a/telegram/cache.go b/telegram/cache.go index bb2d1895..03345e49 100644 --- a/telegram/cache.go +++ b/telegram/cache.go @@ -70,6 +70,7 @@ type CacheConfig struct { MaxSize int // Max size of cache: TODO LogLevel utils.LogLevel LogNoColor bool + LogName string Memory bool Disabled bool } @@ -90,13 +91,14 @@ func NewCache(fileName string, opts ...*CacheConfig) *CACHE { InputUsers: make(map[int64]int64), InputChats: make(map[int64]int64), }, - memory: opt.Memory, - logger: utils.NewLogger("gogram [cache]"). + memory: opt.Memory, + disabled: opt.Disabled, + logger: utils.NewLogger("gogram " + getLogPrefix("cache", opt.LogName)). SetLevel(opt.LogLevel). NoColor(opt.LogNoColor), } - if !c.memory && !opt.Disabled { + if !opt.Memory && !opt.Disabled { c.logger.Debug("initialized cache (" + c.fileName + ") successfully") } @@ -172,7 +174,7 @@ func (c *CACHE) ReadFile() { } defer file.Close() - var totalLoaded int + var totalLoaded = []int{0, 0, 0} c.Lock() for { @@ -198,18 +200,20 @@ func (c *CACHE) ReadFile() { switch entryType { case 1: c.InputPeers.InputUsers[id] = accessHash + totalLoaded[0]++ case 2: c.InputPeers.InputChats[id] = accessHash + totalLoaded[1]++ case 3: c.InputPeers.InputChannels[id] = accessHash + totalLoaded[2]++ } - totalLoaded++ } c.Unlock() - if totalLoaded != 0 { - c.logger.Debug("loaded ", totalLoaded, " peers from cacheFile") + if !c.memory { + c.logger.Debug("loaded ", totalLoaded[0], " users, ", totalLoaded[1], " chats, ", totalLoaded[2], " channels from cache") } } @@ -486,33 +490,58 @@ func (cache *CACHE) UpdatePeersToCache(users []User, chats []Chat) { totalUpdates := [2]int{0, 0} for _, user := range users { - if us, ok := user.(*UserObj); ok { + switch us := user.(type) { + case *UserObj: if updated := cache.UpdateUser(us); updated { totalUpdates[0]++ } + case *UserEmpty: } } for _, chat := range chats { - if ch, ok := chat.(*ChatObj); ok { + switch ch := chat.(type) { + case *ChatObj: if updated := cache.UpdateChat(ch); updated { totalUpdates[1]++ } - } else if channel, ok := chat.(*Channel); ok { - if updated := cache.UpdateChannel(channel); updated { + case *Channel: + if updated := cache.UpdateChannel(ch); updated { totalUpdates[1]++ } + case *ChatForbidden: + cache.Lock() + if _, ok := cache.InputPeers.InputChats[ch.ID]; !ok { + cache.chats[ch.ID] = &ChatObj{ + ID: ch.ID, + } + cache.InputPeers.InputChats[ch.ID] = ch.ID + } + cache.Unlock() + case *ChannelForbidden: + cache.Lock() + if _, ok := cache.InputPeers.InputChannels[ch.ID]; !ok { + cache.channels[ch.ID] = &Channel{ + ID: ch.ID, + Broadcast: ch.Broadcast, + Megagroup: ch.Megagroup, + AccessHash: ch.AccessHash, + Title: ch.Title, + } + cache.InputPeers.InputChannels[ch.ID] = ch.AccessHash + } + cache.Unlock() + case *ChatEmpty: } } if totalUpdates[0] > 0 || totalUpdates[1] > 0 { if !cache.memory { - go cache.WriteFile() // Write to file asynchronously + go cache.WriteFile() // write to file asynchronously } cache.logger.Debug( - fmt.Sprintf("updated %d users and %d chats to %s (users: %d, chats: %d)", - totalUpdates[0], totalUpdates[1], cache.fileName, - len(cache.InputPeers.InputUsers), len(cache.InputPeers.InputChats), + fmt.Sprintf("updated %d users %d chats and %d channels in cache (u: %d, c: %d)", + totalUpdates[0], totalUpdates[1], totalUpdates[1], len(users), len(chats), ), ) } diff --git a/telegram/client.go b/telegram/client.go index 09bba290..e671aefc 100644 --- a/telegram/client.go +++ b/telegram/client.go @@ -66,6 +66,7 @@ type ClientConfig struct { DeviceConfig DeviceConfig Session string StringSession string + SessionName string LangCode string ParseMode string MemorySession bool @@ -76,6 +77,7 @@ type ClientConfig struct { DisableCache bool TestMode bool LogLevel utils.LogLevel + Logger *utils.Logger Proxy *url.URL ForceIPv6 bool Cache *CACHE @@ -101,17 +103,26 @@ func (s *Session) Encode() string { func NewClient(config ClientConfig) (*Client, error) { client := &Client{ wg: sync.WaitGroup{}, - Log: utils.NewLogger("gogram [client]"), stopCh: make(chan struct{}), } + if config.Logger != nil { + client.Log = config.Logger + client.Log.Prefix = "gogram " + getLogPrefix("client ", config.SessionName) + config.LogLevel = config.Logger.Lev() + } else { + client.Log = utils.NewLogger("gogram " + getLogPrefix("client ", config.SessionName)) + } + config = client.cleanClientConfig(config) client.setupClientData(config) if config.Cache == nil { - client.Cache = NewCache("cache.db", &CacheConfig{ - Disabled: config.DisableCache, - LogLevel: config.LogLevel, + client.Cache = NewCache(fmt.Sprintf("cache%s.db", config.SessionName), &CacheConfig{ + Disabled: config.DisableCache, + LogLevel: config.LogLevel, + LogName: config.SessionName, + LogNoColor: !client.Log.Color(), }) } else { client.Cache = config.Cache @@ -149,7 +160,7 @@ func (c *Client) setupMTProto(config ClientConfig) error { ServerHost: toIpAddr(), PublicKey: config.PublicKeys[0], DataCenter: config.DataCenter, - Logger: utils.NewLogger("gogram [mtproto]"). + Logger: utils.NewLogger("gogram " + getLogPrefix("mtproto", config.SessionName)). SetLevel(config.LogLevel). NoColor(!c.Log.Color()), StringSession: config.StringSession, diff --git a/telegram/const.go b/telegram/const.go index 4ec95c1f..1f010468 100644 --- a/telegram/const.go +++ b/telegram/const.go @@ -8,7 +8,7 @@ import ( const ( ApiVersion = 195 - Version = "v1.4.4" + Version = "v1.4.5" LogDebug = utils.DebugLevel LogInfo = utils.InfoLevel diff --git a/telegram/updates.go b/telegram/updates.go index bedc1684..c8f86bdf 100644 --- a/telegram/updates.go +++ b/telegram/updates.go @@ -153,6 +153,7 @@ func (h *inlineHandle) GetGroup() string { type callbackHandle struct { Pattern any Handler CallbackHandler + Filters []Filter Group string sortTrigger chan any } @@ -235,9 +236,9 @@ type UpdateDispatcher struct { } // creates and populates a new UpdateDispatcher -func (c *Client) NewUpdateDispatcher() { +func (c *Client) NewUpdateDispatcher(sessionName ...string) { c.dispatcher = &UpdateDispatcher{ - logger: utils.NewLogger("gogram [dispatcher]"). + logger: utils.NewLogger("gogram " + getLogPrefix("dispatcher", getVariadic(sessionName, ""))). SetLevel(c.Log.Lev()), } c.dispatcher.SortTrigger() @@ -370,7 +371,7 @@ func (c *Client) handleMessageUpdate(update Message) { if handler.IsMatch(msg.Message, c) { handle := func(h *messageHandle) error { packed := packMessage(c, msg) - if c.runFilterChain(packed, h.Filters) { + if handler.runFilterChain(packed, h.Filters) { defer c.NewRecovery()() if err := h.Handler(packed); err != nil { if errors.Is(err, EndGroup) { @@ -497,7 +498,7 @@ func (c *Client) handleEditUpdate(update Message) { handle := func(h *messageEditHandle) error { packed := packMessage(c, msg) defer c.NewRecovery()() - if c.runFilterChain(packed, h.Filters) { + if handler.runFilterChain(packed, h.Filters) { if err := h.Handler(packed); err != nil { if errors.Is(err, EndGroup) { return err @@ -527,12 +528,14 @@ func (c *Client) handleCallbackUpdate(update *UpdateBotCallbackQuery) { if handler.IsMatch(update.Data) { handle := func(h *callbackHandle) error { packed := packCallbackQuery(c, update) - defer c.NewRecovery()() - if err := h.Handler(packed); err != nil { - if errors.Is(err, EndGroup) { - return err + if handler.runFilterChain(packed, h.Filters) { + defer c.NewRecovery()() + if err := h.Handler(packed); err != nil { + if errors.Is(err, EndGroup) { + return err + } + c.Log.Error(errors.Wrap(err, "[callbackQuery]")) } - c.Log.Error(errors.Wrap(err, "[callbackQuery]")) } return nil } @@ -754,8 +757,8 @@ func (h *messageHandle) IsMatch(text string, c *Client) bool { } if strings.HasPrefix(Pattern, "cmd:") { - //(?i)^[!/-]ping(?: |$|@botusername)(.*)$ - Pattern = "(?i)^[!/]" + strings.TrimPrefix(Pattern, "cmd:") + //(?i)^[!/-?]ping(?: |$|@botusername)(.*)$ + Pattern = "(?i)^[!/?]" + strings.TrimPrefix(Pattern, "cmd:") if me := c.Me(); me != nil && me.Username != "" && me.Bot { Pattern += "(?: |$|@" + me.Username + ")(.*)" } else { @@ -775,7 +778,7 @@ func (h *messageHandle) IsMatch(text string, c *Client) bool { return false } -func (c *Client) runFilterChain(m *NewMessage, filters []Filter) bool { +func (h *messageHandle) runFilterChain(m *NewMessage, filters []Filter) bool { var ( actAsBlacklist bool actUsers, actGroups []int64 @@ -845,10 +848,39 @@ func (c *Client) runFilterChain(m *NewMessage, filters []Filter) bool { return true } +func (h *messageEditHandle) runFilterChain(m *NewMessage, filters []Filter) bool { + var message = &messageHandle{} + return message.runFilterChain(m, filters) +} + +func (h *callbackHandle) runFilterChain(c *CallbackQuery, filters []Filter) bool { + if len(filters) > 0 { + for _, filter := range filters { + if filter.Private && !c.IsPrivate() || filter.Group && !c.IsGroup() || filter.Channel && !c.IsChannel() { + return false + } + if filter.FromBot { + if c.Sender == nil || !c.Sender.Bot { + return false + } + } + + if filter.Func != nil { + if !filter.FuncCallback(c) { + return false + } + } + } + } + + return true +} + type Filter struct { Private, Group, Channel, Media, Command, Reply, Forward, FromBot, Blacklist, Mention bool Users, Chats []int64 Func func(m *NewMessage) bool + FuncCallback func(c *CallbackQuery) bool } var ( @@ -871,6 +903,9 @@ var ( FilterFunc = func(f func(m *NewMessage) bool) Filter { return Filter{Func: f} } + FilterFuncCallback = func(f func(c *CallbackQuery) bool) Filter { + return Filter{Func: func(m *NewMessage) bool { return true }} + } ) func (c *Client) AddMessageHandler(pattern any, handler MessageHandler, filters ...Filter) Handle { @@ -937,11 +972,16 @@ func (c *Client) AddActionHandler(handler MessageHandler) Handle { // - Message Edited // - Channel Post Edited func (c *Client) AddEditHandler(pattern any, handler MessageHandler, filters ...Filter) Handle { + var messageFilters []Filter + if len(filters) > 0 { + messageFilters = filters + } + if c.dispatcher.messageEditHandles == nil { c.dispatcher.messageEditHandles = make(map[string][]*messageEditHandle) } - handle := messageEditHandle{Pattern: pattern, Handler: handler, sortTrigger: c.dispatcher.sortTrigger} + handle := messageEditHandle{Pattern: pattern, Handler: handler, sortTrigger: c.dispatcher.sortTrigger, Filters: messageFilters} c.dispatcher.messageEditHandles["default"] = append(c.dispatcher.messageEditHandles["default"], &handle) return c.dispatcher.messageEditHandles["default"][len(c.dispatcher.messageEditHandles["default"])-1] } @@ -964,12 +1004,17 @@ func (c *Client) AddInlineHandler(pattern any, handler InlineHandler) Handle { // // Included Updates: // - Callback Query -func (c *Client) AddCallbackHandler(pattern any, handler CallbackHandler) Handle { +func (c *Client) AddCallbackHandler(pattern any, handler CallbackHandler, filters ...Filter) Handle { + var messageFilters []Filter + if len(filters) > 0 { + messageFilters = filters + } + if c.dispatcher.callbackHandles == nil { c.dispatcher.callbackHandles = make(map[string][]*callbackHandle) } - handle := callbackHandle{Pattern: pattern, Handler: handler, sortTrigger: c.dispatcher.sortTrigger} + handle := callbackHandle{Pattern: pattern, Handler: handler, sortTrigger: c.dispatcher.sortTrigger, Filters: messageFilters} c.dispatcher.callbackHandles["default"] = append(c.dispatcher.callbackHandles["default"], &handle) return c.dispatcher.callbackHandles["default"][len(c.dispatcher.callbackHandles["default"])-1] } diff --git a/telegram/utils.go b/telegram/utils.go index ff3f6407..82d42404 100755 --- a/telegram/utils.go +++ b/telegram/utils.go @@ -17,6 +17,7 @@ import ( "strings" "time" + "github.com/amarnathcjd/gogram/internal/utils" "github.com/pkg/errors" ) @@ -435,6 +436,13 @@ func getPeerUser(userID int64) *PeerUser { } } +func getLogPrefix(loggerName string, sessionName string) string { + if sessionName == "" { + return fmt.Sprintf("[%s]", loggerName) + } + return fmt.Sprintf("[%s] {%s}", loggerName, sessionName) +} + func IsURL(str string) bool { u, err := url.Parse(str) return err == nil && u.Scheme != "" && u.Host != "" @@ -676,3 +684,7 @@ func IsFfmpegInstalled() bool { _, err := exec.LookPath("ffmpeg") return err == nil } + +func NewLogger(level utils.LogLevel, prefix ...string) *utils.Logger { + return utils.NewLogger(getVariadic(prefix, "gogram")).SetLevel(level) +}