feat(irc): improve reconnect and add notifications (#315)

* refactor(irc): nickserv and methods

* feat(notifications): add new events and refactor send

* feat(irc): handle disconnect reconnect and connect

* feat(irc): update config for ergo local irc server

* feat(irc): retry initial connect

* feat(irc): show nickserv errors
This commit is contained in:
Ludvig Lundgren 2022-06-29 16:50:38 +02:00 committed by GitHub
parent 41eef4e8be
commit f63ace662a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 1343 additions and 133 deletions

View file

@ -9,6 +9,7 @@ import (
"github.com/autobrr/autobrr/internal/domain"
"github.com/autobrr/autobrr/internal/indexer"
"github.com/autobrr/autobrr/internal/logger"
"github.com/autobrr/autobrr/internal/notification"
"github.com/autobrr/autobrr/internal/release"
"github.com/pkg/errors"
@ -28,24 +29,26 @@ type Service interface {
}
type service struct {
log logger.Logger
repo domain.IrcRepo
releaseService release.Service
indexerService indexer.Service
indexerMap map[string]string
handlers map[handlerKey]*Handler
log logger.Logger
repo domain.IrcRepo
releaseService release.Service
indexerService indexer.Service
notificationService notification.Service
indexerMap map[string]string
handlers map[handlerKey]*Handler
stopWG sync.WaitGroup
lock sync.Mutex
}
func NewService(log logger.Logger, repo domain.IrcRepo, releaseSvc release.Service, indexerSvc indexer.Service) Service {
func NewService(log logger.Logger, repo domain.IrcRepo, releaseSvc release.Service, indexerSvc indexer.Service, notificationSvc notification.Service) Service {
return &service{
log: log,
repo: repo,
releaseService: releaseSvc,
indexerService: indexerSvc,
handlers: make(map[handlerKey]*Handler),
log: log,
repo: repo,
releaseService: releaseSvc,
indexerService: indexerSvc,
notificationService: notificationSvc,
handlers: make(map[handlerKey]*Handler),
}
}
@ -79,7 +82,7 @@ func (s *service) StartHandlers() {
definitions := s.indexerService.GetIndexersByIRCNetwork(network.Server)
// init new irc handler
handler := NewHandler(s.log, network, definitions, s.releaseService)
handler := NewHandler(s.log, network, definitions, s.releaseService, s.notificationService)
// use network.Server + nick to use multiple indexers with different nick per network
// this allows for multiple handlers to one network
@ -135,7 +138,7 @@ func (s *service) startNetwork(network domain.IrcNetwork) error {
definitions := s.indexerService.GetIndexersByIRCNetwork(network.Server)
// init new irc handler
handler := NewHandler(s.log, network, definitions, s.releaseService)
handler := NewHandler(s.log, network, definitions, s.releaseService, s.notificationService)
s.handlers[handlerKey{network.Server, network.NickServ.Account}] = handler
s.lock.Unlock()
@ -198,15 +201,13 @@ func (s *service) checkIfNetworkRestartNeeded(network *domain.IrcNetwork) error
if handler.NickServ.Account != network.NickServ.Account {
s.log.Debug().Msg("changing nick")
err := existingHandler.HandleNickChange(network.NickServ.Account)
if err != nil {
if err := existingHandler.NickChange(network.NickServ.Account); err != nil {
s.log.Error().Stack().Err(err).Msgf("failed to change nick %q", network.NickServ.Account)
}
} else if handler.NickServ.Password != network.NickServ.Password {
s.log.Debug().Msg("nickserv: changing password")
err := existingHandler.HandleNickServIdentify(network.NickServ.Password)
if err != nil {
if err := existingHandler.NickServIdentify(network.NickServ.Password); err != nil {
s.log.Error().Stack().Err(err).Msgf("failed to identify with nickserv %q", network.NickServ.Account)
}
}
@ -252,8 +253,8 @@ func (s *service) checkIfNetworkRestartNeeded(network *domain.IrcNetwork) error
// leave channels
for _, leaveChannel := range channelsToLeave {
s.log.Debug().Msgf("%v: part channel %v", network.Server, leaveChannel)
err := existingHandler.HandlePartChannel(leaveChannel)
if err != nil {
if err := existingHandler.PartChannel(leaveChannel); err != nil {
s.log.Error().Stack().Err(err).Msgf("failed to leave channel: %q", leaveChannel)
}
}
@ -261,8 +262,8 @@ func (s *service) checkIfNetworkRestartNeeded(network *domain.IrcNetwork) error
// join channels
for _, joinChannel := range channelsToJoin {
s.log.Debug().Msgf("%v: join new channel %v", network.Server, joinChannel)
err := existingHandler.HandleJoinChannel(joinChannel.Name, joinChannel.Password)
if err != nil {
if err := existingHandler.JoinChannel(joinChannel.Name, joinChannel.Password); err != nil {
s.log.Error().Stack().Err(err).Msgf("failed to join channel: %q", joinChannel.Name)
}
}
@ -386,17 +387,18 @@ func (s *service) GetNetworksWithHealth(ctx context.Context) ([]domain.IrcNetwor
for _, n := range networks {
netw := domain.IrcNetworkWithHealth{
ID: n.ID,
Name: n.Name,
Enabled: n.Enabled,
Server: n.Server,
Port: n.Port,
TLS: n.TLS,
Pass: n.Pass,
InviteCommand: n.InviteCommand,
NickServ: n.NickServ,
Connected: false,
Channels: []domain.ChannelWithHealth{},
ID: n.ID,
Name: n.Name,
Enabled: n.Enabled,
Server: n.Server,
Port: n.Port,
TLS: n.TLS,
Pass: n.Pass,
InviteCommand: n.InviteCommand,
NickServ: n.NickServ,
Connected: false,
Channels: []domain.ChannelWithHealth{},
ConnectionErrors: []string{},
}
handler, ok := s.handlers[handlerKey{n.Server, n.NickServ.Account}]
@ -404,10 +406,21 @@ func (s *service) GetNetworksWithHealth(ctx context.Context) ([]domain.IrcNetwor
// only set connected and connected since if we have an active handler and connection
if handler.client.Connected() {
handler.m.RLock()
netw.Connected = handler.connected
netw.ConnectedSince = handler.connectedSince
// current and preferred nick is only available if the network is connected
netw.CurrentNick = handler.CurrentNick()
netw.PreferredNick = handler.PreferredNick()
handler.m.RUnlock()
}
// if we have any connection errors like bad nickserv auth add them here
if len(handler.connectionErrors) > 0 {
netw.ConnectionErrors = handler.connectionErrors
}
}
channels, err := s.repo.ListChannels(n.ID)