3
0
mirror of https://github.com/ergochat/ergo.git synced 2024-11-22 03:49:27 +01:00
ergo/irc/accept.go
Shivaram Lingamneni c5579a6a34 fix #1688
* Add ACCEPT-tracking functionality (authorizing users to send DMs
  despite +R or other applicable restrictions)
* Sending a DM automatically accepts the recipient
* Add explicit ACCEPT command
2022-05-05 22:34:43 -04:00

77 lines
1.9 KiB
Go

package irc
import (
"sync"
"github.com/ergochat/ergo/irc/utils"
)
// tracks ACCEPT relationships, i.e., `accepter` is willing to receive DMs from
// `accepted` despite some restriction (currently the only relevant restriction
// is that `accepter` is +R and `accepted` is not logged in)
type AcceptManager struct {
sync.RWMutex
// maps recipient -> whitelist of permitted senders:
// this is what we actually check
clientToAccepted map[*Client]utils.HashSet[*Client]
// this is the reverse mapping, it's needed so we can
// clean up the forward mapping during (*Client).destroy():
clientToAccepters map[*Client]utils.HashSet[*Client]
}
func (am *AcceptManager) Initialize() {
am.clientToAccepted = make(map[*Client]utils.HashSet[*Client])
am.clientToAccepters = make(map[*Client]utils.HashSet[*Client])
}
func (am *AcceptManager) MaySendTo(sender, recipient *Client) (result bool) {
am.RLock()
defer am.RUnlock()
return am.clientToAccepted[recipient].Has(sender)
}
func (am *AcceptManager) Accept(accepter, accepted *Client) {
am.Lock()
defer am.Unlock()
var m utils.HashSet[*Client]
m = am.clientToAccepted[accepter]
if m == nil {
m = make(utils.HashSet[*Client])
am.clientToAccepted[accepter] = m
}
m.Add(accepted)
m = am.clientToAccepters[accepted]
if m == nil {
m = make(utils.HashSet[*Client])
am.clientToAccepters[accepted] = m
}
m.Add(accepter)
}
func (am *AcceptManager) Unaccept(accepter, accepted *Client) {
am.Lock()
defer am.Unlock()
delete(am.clientToAccepted[accepter], accepted)
delete(am.clientToAccepters[accepted], accepter)
}
func (am *AcceptManager) Remove(client *Client) {
am.Lock()
defer am.Unlock()
for accepter := range am.clientToAccepters[client] {
delete(am.clientToAccepted[accepter], client)
}
for accepted := range am.clientToAccepted[client] {
delete(am.clientToAccepters[accepted], client)
}
delete(am.clientToAccepters, client)
delete(am.clientToAccepted, client)
}