mirror of
				https://github.com/42wim/matterbridge.git
				synced 2025-11-03 23:37:24 +01:00 
			
		
		
		
	Change activity to per-channel
This commit is contained in:
		
							parent
							
								
									26bda54e16
								
							
						
					
					
						commit
						edbf9c310b
					
				@ -36,9 +36,6 @@ type Bdiscord struct {
 | 
			
		||||
	userMemberMap map[string]*discordgo.Member
 | 
			
		||||
	nickMemberMap map[string]*discordgo.Member
 | 
			
		||||
 | 
			
		||||
	noEmbedPartUrls bool
 | 
			
		||||
	noEmbedUrls     bool
 | 
			
		||||
 | 
			
		||||
	// Webhook specific logic
 | 
			
		||||
	useAutoWebhooks bool
 | 
			
		||||
	transmitter     *transmitter.Transmitter
 | 
			
		||||
@ -60,12 +57,6 @@ func New(cfg *bridge.Config) bridge.Bridger {
 | 
			
		||||
	b.nickMemberMap = make(map[string]*discordgo.Member)
 | 
			
		||||
	b.channelInfoMap = make(map[string]*config.ChannelInfo)
 | 
			
		||||
 | 
			
		||||
	b.noEmbedPartUrls = b.GetBool(("NoEmbedPartUrls"))
 | 
			
		||||
	b.noEmbedUrls = b.GetBool(("NoEmbedUrls"))
 | 
			
		||||
	if b.noEmbedPartUrls && b.noEmbedUrls {
 | 
			
		||||
		b.Log.Info("NoEmbedUrls supersedes NoEmbedPartUrls")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	b.useAutoWebhooks = b.GetBool("AutoWebhooks")
 | 
			
		||||
	if b.useAutoWebhooks {
 | 
			
		||||
		b.Log.Debug("Using automatic webhooks")
 | 
			
		||||
@ -278,10 +269,6 @@ func (b *Bdiscord) Send(msg config.Message) (string, error) {
 | 
			
		||||
		msg.Text = "_" + msg.Text + "_"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if b.noEmbedUrls || (msg.Event == config.EventJoinLeave && b.noEmbedPartUrls) {
 | 
			
		||||
		disableEmbedUrls(&msg.Text)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Handle prefix hint for unthreaded messages.
 | 
			
		||||
	if msg.ParentNotFound() {
 | 
			
		||||
		msg.ParentID = ""
 | 
			
		||||
 | 
			
		||||
@ -233,11 +233,6 @@ func (b *Bdiscord) splitURL(url string) (string, string, bool) {
 | 
			
		||||
	return webhookURLSplit[webhookIdxID], webhookURLSplit[webhookIdxToken], true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func disableEmbedUrls(msg *string) {
 | 
			
		||||
	regex := regexp.MustCompile(`(\w+://\S+)`)
 | 
			
		||||
	*msg = regex.ReplaceAllString(*msg, "<$1>")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func enumerateUsernames(s string) []string {
 | 
			
		||||
	onlySpace := true
 | 
			
		||||
	for _, r := range s {
 | 
			
		||||
 | 
			
		||||
@ -114,7 +114,8 @@ func (b *Birc) handleJoinPart(client *girc.Client, event girc.Event) {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if event.Source.Name != b.Nick {
 | 
			
		||||
		if isActive, _ := b.isUserActive(event.Source.Name); !isActive || b.GetBool("nosendjoinpart") {
 | 
			
		||||
		if isActive, _ := b.isUserActive(event.Source.Name, channel); !isActive ||
 | 
			
		||||
			b.GetBool("nosendjoinpart") {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		partmsg := ""
 | 
			
		||||
@ -160,19 +161,21 @@ func (b *Birc) handleNick(client *girc.Client, event girc.Event) {
 | 
			
		||||
	if b.GetBool("nosendjoinpart") {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if isActive, activeTime := b.isUserActive(event.Source.Name); isActive {
 | 
			
		||||
		msg := config.Message{
 | 
			
		||||
			Username: "system",
 | 
			
		||||
			Text:     event.Source.Name + " changed nick to " + event.Params[0],
 | 
			
		||||
			Channel:  b.getPseudoChannel(),
 | 
			
		||||
			Account:  b.Account,
 | 
			
		||||
			Event:    config.EventJoinLeave,
 | 
			
		||||
		}
 | 
			
		||||
		b.Log.Debugf("<= Message is %#v", msg)
 | 
			
		||||
		b.Remote <- msg
 | 
			
		||||
		if b.ActivityTimeout != 0 {
 | 
			
		||||
			// This doesn't count as new activity, but it does preserve the value
 | 
			
		||||
			b.markUserActive(event.Params[0], activeTime)
 | 
			
		||||
	if activeChannels := b.getActiveChannels(event.Source.Name); len(activeChannels) > 0 {
 | 
			
		||||
		for _, activityInfo := range activeChannels {
 | 
			
		||||
			msg := config.Message{
 | 
			
		||||
				Username: "system",
 | 
			
		||||
				Text:     event.Source.Name + " changed nick to " + event.Params[0],
 | 
			
		||||
				Channel:  activityInfo.channel,
 | 
			
		||||
				Account:  b.Account,
 | 
			
		||||
				Event:    config.EventJoinLeave,
 | 
			
		||||
			}
 | 
			
		||||
			b.Log.Debugf("<= Message is %#v", msg)
 | 
			
		||||
			b.Remote <- msg
 | 
			
		||||
			if b.ActivityTimeout != 0 {
 | 
			
		||||
				// This doesn't count as new activity, but it does preserve the value
 | 
			
		||||
				b.markUserActive(event.Params[0], activityInfo.channel, activityInfo.activeTime)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -229,9 +232,10 @@ func (b *Birc) handlePrivMsg(client *girc.Client, event girc.Event) {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	channel := strings.ToLower(event.Params[0])
 | 
			
		||||
	rmsg := config.Message{
 | 
			
		||||
		Username: event.Source.Name,
 | 
			
		||||
		Channel:  strings.ToLower(event.Params[0]),
 | 
			
		||||
		Channel:  channel,
 | 
			
		||||
		Account:  b.Account,
 | 
			
		||||
		UserID:   event.Source.Ident + "@" + event.Source.Host,
 | 
			
		||||
	}
 | 
			
		||||
@ -284,7 +288,7 @@ func (b *Birc) handlePrivMsg(client *girc.Client, event girc.Event) {
 | 
			
		||||
	b.Log.Debugf("<= Sending message from %s on %s to gateway", event.Params[0], b.Account)
 | 
			
		||||
	if b.ActivityTimeout > 0 {
 | 
			
		||||
		b.Log.Debugf("<= Updating last-active time for user %s", event.Source.Name)
 | 
			
		||||
		b.markUserActive(event.Source.Name, time.Now().Unix())
 | 
			
		||||
		b.markUserActive(event.Source.Name, channel, time.Now().Unix())
 | 
			
		||||
	}
 | 
			
		||||
	b.Remote <- rmsg
 | 
			
		||||
	b.cleanActiveMap()
 | 
			
		||||
@ -293,23 +297,30 @@ func (b *Birc) handlePrivMsg(client *girc.Client, event girc.Event) {
 | 
			
		||||
func (b *Birc) handleQuit(client *girc.Client, event girc.Event) {
 | 
			
		||||
	if event.Source.Name == b.Nick && strings.Contains(event.Last(), "Ping timeout") {
 | 
			
		||||
		b.Log.Infof("%s reconnecting ..", b.Account)
 | 
			
		||||
		b.Remote <- config.Message{Username: "system", Text: "reconnect", Channel: b.getPseudoChannel(), Account: b.Account, Event: config.EventFailure}
 | 
			
		||||
		for mychan := range b.channels {
 | 
			
		||||
			b.Remote <- config.Message{Username: "system", Text: "reconnect", Channel: mychan, Account: b.Account, Event: config.EventFailure}
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	} else if b.GetBool("nosendjoinpart") {
 | 
			
		||||
		return
 | 
			
		||||
	} else if isActive, _ := b.isUserActive(event.Source.Name); isActive || isKill(event.Last()) {
 | 
			
		||||
	} else if activeChannels, found := b.activeUsers[event.Source.Name]; found {
 | 
			
		||||
		userWasKilled := isKill(event.Last())
 | 
			
		||||
		verbosequit := ""
 | 
			
		||||
		quitmsg := ""
 | 
			
		||||
		nowTime := time.Now().Unix()
 | 
			
		||||
		if len(event.Params) >= 1 {
 | 
			
		||||
			quitmsg = " with message: " + event.Last()
 | 
			
		||||
		}
 | 
			
		||||
		if b.GetBool("verbosejoinpart") {
 | 
			
		||||
			verbosequit = " (" + event.Source.Ident + "@" + event.Source.Host + ")"
 | 
			
		||||
		}
 | 
			
		||||
		msg := config.Message{Username: "system", Text: event.Source.Name + verbosequit + " quit" + quitmsg, Channel: b.getPseudoChannel(), Account: b.Account, Event: config.EventJoinLeave}
 | 
			
		||||
		b.Log.Debugf("<= Message is %#v", msg)
 | 
			
		||||
		b.Remote <- msg
 | 
			
		||||
		return
 | 
			
		||||
		for channel, activeTime := range activeChannels {
 | 
			
		||||
			if userWasKilled || b.isActive(activeTime, nowTime) {
 | 
			
		||||
				msg := config.Message{Username: "system", Text: event.Source.Name + verbosequit + " quit" + quitmsg, Channel: channel, Account: b.Account, Event: config.EventJoinLeave}
 | 
			
		||||
				b.Log.Debugf("<= Message is %#v", msg)
 | 
			
		||||
				b.Remote <- msg
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -28,7 +28,7 @@ type Birc struct {
 | 
			
		||||
	i                                         *girc.Client
 | 
			
		||||
	Nick                                      string
 | 
			
		||||
	names                                     map[string][]string
 | 
			
		||||
	activeUsers                               map[string]int64
 | 
			
		||||
	activeUsers                               map[string]map[string]int64
 | 
			
		||||
	activeUsersLastCleaned                    int64
 | 
			
		||||
	activeUsersMutex                          sync.RWMutex
 | 
			
		||||
	connected                                 chan error
 | 
			
		||||
@ -41,12 +41,17 @@ type Birc struct {
 | 
			
		||||
	*bridge.Config
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ActivityInfo struct {
 | 
			
		||||
	channel    string
 | 
			
		||||
	activeTime int64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func New(cfg *bridge.Config) bridge.Bridger {
 | 
			
		||||
	b := &Birc{}
 | 
			
		||||
	b.Config = cfg
 | 
			
		||||
	b.Nick = b.GetString("Nick")
 | 
			
		||||
	b.names = make(map[string][]string)
 | 
			
		||||
	b.activeUsers = make(map[string]int64)
 | 
			
		||||
	b.activeUsers = make(map[string]map[string]int64)
 | 
			
		||||
	b.connected = make(chan error)
 | 
			
		||||
	b.channels = make(map[string]bool)
 | 
			
		||||
 | 
			
		||||
@ -434,33 +439,45 @@ func (b *Birc) getTLSConfig() (*tls.Config, error) {
 | 
			
		||||
	return tlsConfig, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b *Birc) isUserActive(nick string) (bool, int64) {
 | 
			
		||||
func (b *Birc) isActive(activityTime int64, nowTime int64) bool {
 | 
			
		||||
	return (nowTime - activityTime) < b.ActivityTimeout
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b *Birc) isUserActive(nick string, channel string) (bool, int64) {
 | 
			
		||||
	b.Log.Debugf("checking activity for %s", nick)
 | 
			
		||||
	if b.ActivityTimeout == 0 {
 | 
			
		||||
		return true, 0
 | 
			
		||||
	}
 | 
			
		||||
	b.activeUsersMutex.RLock()
 | 
			
		||||
	defer b.activeUsersMutex.RUnlock()
 | 
			
		||||
	if activeTime, ok := b.activeUsers[nick]; ok {
 | 
			
		||||
	if activeTime, ok := b.activeUsers[nick][channel]; ok {
 | 
			
		||||
		now := time.Now().Unix()
 | 
			
		||||
		b.Log.Debugf("last activity for %s was %d, currently %d", nick, activeTime, now)
 | 
			
		||||
		if now < activeTime {
 | 
			
		||||
			b.Log.Errorf("User %s has active time in the future: %d", nick, activeTime)
 | 
			
		||||
			return true, now // err on the side of caution
 | 
			
		||||
		}
 | 
			
		||||
		return (now - activeTime) < b.ActivityTimeout, activeTime
 | 
			
		||||
		return b.isActive(now, activeTime), activeTime
 | 
			
		||||
	}
 | 
			
		||||
	return false, 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b *Birc) getPseudoChannel() string {
 | 
			
		||||
	for channelname, active := range b.channels {
 | 
			
		||||
		if active {
 | 
			
		||||
			return channelname
 | 
			
		||||
func (b *Birc) getActiveChannels(nick string) []ActivityInfo {
 | 
			
		||||
	retval := make([]ActivityInfo, 0)
 | 
			
		||||
	if channels, found := b.activeUsers[nick]; found {
 | 
			
		||||
		now := time.Now().Unix()
 | 
			
		||||
		for channel, activeTime := range channels {
 | 
			
		||||
			if now < activeTime {
 | 
			
		||||
				b.Log.Errorf("User %s has active time for channel %s in the future: %d",
 | 
			
		||||
					nick,
 | 
			
		||||
					channel,
 | 
			
		||||
					activeTime)
 | 
			
		||||
			} else if (now - activeTime) < b.ActivityTimeout {
 | 
			
		||||
				retval = append(retval, ActivityInfo{channel, activeTime})
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	b.Log.Warningf("Bot not active in any channels!")
 | 
			
		||||
	return ""
 | 
			
		||||
	return retval
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b *Birc) cleanActiveMap() {
 | 
			
		||||
@ -470,16 +487,26 @@ func (b *Birc) cleanActiveMap() {
 | 
			
		||||
	}
 | 
			
		||||
	b.activeUsersMutex.Lock()
 | 
			
		||||
	defer b.activeUsersMutex.Unlock()
 | 
			
		||||
	for nick, activeTime := range b.activeUsers {
 | 
			
		||||
		if now-activeTime > b.ActivityTimeout {
 | 
			
		||||
			b.Log.Debugf("last activity for %s was %d, currently %d. Deleting.", nick, activeTime, now)
 | 
			
		||||
	for nick, activeChannels := range b.activeUsers {
 | 
			
		||||
		for channel, activeTime := range activeChannels {
 | 
			
		||||
			if now-activeTime > b.ActivityTimeout {
 | 
			
		||||
				b.Log.Debugf("last activity for %s was %d, currently %d. Deleting.", nick, activeTime, now)
 | 
			
		||||
				delete(activeChannels, channel)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if 0 == len(activeChannels) {
 | 
			
		||||
			delete(b.activeUsers, nick)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b *Birc) markUserActive(nick string, activeTime int64) {
 | 
			
		||||
func (b *Birc) markUserActive(nick string, channel string, activeTime int64) {
 | 
			
		||||
	b.activeUsersMutex.Lock()
 | 
			
		||||
	defer b.activeUsersMutex.Unlock()
 | 
			
		||||
	b.activeUsers[nick] = activeTime
 | 
			
		||||
	nickActivity, found := b.activeUsers[nick]
 | 
			
		||||
	if !found {
 | 
			
		||||
		b.activeUsers[nick] = make(map[string]int64)
 | 
			
		||||
		nickActivity = b.activeUsers[nick]
 | 
			
		||||
	}
 | 
			
		||||
	nickActivity[channel] = activeTime
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -947,15 +947,6 @@ IgnoreNicks=""
 | 
			
		||||
#   IgnoreMessages="^~~ badword"
 | 
			
		||||
IgnoreMessages=""
 | 
			
		||||
 | 
			
		||||
# Prevent URL embeds by encasing URLs in <> angle brackets.
 | 
			
		||||
# Useful if trolls are a problem on the other end of your bridge.
 | 
			
		||||
NoEmbedUrls=false
 | 
			
		||||
 | 
			
		||||
# Prevent URL embeds in part/quit messages by encasing URLs in <> angle brackets.
 | 
			
		||||
# Useful if trolls spam in their quit messages or you're tired of seeing embeds for
 | 
			
		||||
# IRC client homepages.
 | 
			
		||||
NoEmbedPartUrls=false
 | 
			
		||||
 | 
			
		||||
# ReplaceMessages replaces substrings of messages in outgoing messages.
 | 
			
		||||
# Regular expressions are supported.
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user