mirror of
https://github.com/idanoo/autobrr
synced 2025-07-23 00:39:13 +00:00

* refactor: update http handlers * feat: add trace log level * refactir: irc handler * refactor(definitions): add irc settings and invite cmd: * feat: add dft values to inputs * refactor: indexer irc forms * refactor(definitions): fix nickserv.password var: * feat: pre fill indexer name field * refactor: handle stopping and updates
257 lines
6 KiB
Go
257 lines
6 KiB
Go
package irc
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"sync"
|
|
|
|
"github.com/autobrr/autobrr/internal/announce"
|
|
"github.com/autobrr/autobrr/internal/domain"
|
|
|
|
"github.com/rs/zerolog/log"
|
|
)
|
|
|
|
type Service interface {
|
|
StartHandlers()
|
|
StopHandlers()
|
|
StopNetwork(name string) error
|
|
ListNetworks(ctx context.Context) ([]domain.IrcNetwork, error)
|
|
GetNetworkByID(id int64) (*domain.IrcNetwork, error)
|
|
DeleteNetwork(ctx context.Context, id int64) error
|
|
StoreNetwork(network *domain.IrcNetwork) error
|
|
StoreChannel(networkID int64, channel *domain.IrcChannel) error
|
|
}
|
|
|
|
type service struct {
|
|
repo domain.IrcRepo
|
|
announceService announce.Service
|
|
indexerMap map[string]string
|
|
handlers map[string]*Handler
|
|
|
|
stopWG sync.WaitGroup
|
|
lock sync.Mutex
|
|
}
|
|
|
|
func NewService(repo domain.IrcRepo, announceService announce.Service) Service {
|
|
return &service{
|
|
repo: repo,
|
|
announceService: announceService,
|
|
handlers: make(map[string]*Handler),
|
|
}
|
|
}
|
|
|
|
func (s *service) StartHandlers() {
|
|
networks, err := s.repo.ListNetworks(context.Background())
|
|
if err != nil {
|
|
log.Error().Msgf("failed to list networks: %v", err)
|
|
}
|
|
|
|
for _, network := range networks {
|
|
if !network.Enabled {
|
|
continue
|
|
}
|
|
|
|
// check if already in handlers
|
|
//v, ok := s.handlers[network.Name]
|
|
|
|
s.lock.Lock()
|
|
channels, err := s.repo.ListChannels(network.ID)
|
|
if err != nil {
|
|
log.Error().Err(err).Msgf("failed to list channels for network %q", network.Server)
|
|
}
|
|
network.Channels = channels
|
|
|
|
handler := NewHandler(network, s.announceService)
|
|
|
|
s.handlers[network.Name] = handler
|
|
s.lock.Unlock()
|
|
|
|
log.Debug().Msgf("starting network: %+v", network.Name)
|
|
|
|
s.stopWG.Add(1)
|
|
|
|
go func() {
|
|
if err := handler.Run(); err != nil {
|
|
log.Error().Err(err).Msgf("failed to start handler for network %q", network.Name)
|
|
}
|
|
}()
|
|
|
|
s.stopWG.Done()
|
|
}
|
|
}
|
|
|
|
func (s *service) StopHandlers() {
|
|
for _, handler := range s.handlers {
|
|
log.Info().Msgf("stopping network: %+v", handler.network.Name)
|
|
handler.Stop()
|
|
}
|
|
|
|
log.Info().Msg("stopped all irc handlers")
|
|
}
|
|
|
|
func (s *service) startNetwork(network domain.IrcNetwork) error {
|
|
// look if we have the network in handlers already, if so start it
|
|
if handler, found := s.handlers[network.Name]; found {
|
|
log.Debug().Msgf("starting network: %+v", network.Name)
|
|
|
|
if handler.conn != nil {
|
|
go func() {
|
|
if err := handler.Run(); err != nil {
|
|
log.Error().Err(err).Msgf("failed to start handler for network %q", handler.network.Name)
|
|
}
|
|
}()
|
|
}
|
|
} else {
|
|
// if not found in handlers, lets add it and run it
|
|
|
|
handler := NewHandler(network, s.announceService)
|
|
|
|
s.lock.Lock()
|
|
s.handlers[network.Name] = handler
|
|
s.lock.Unlock()
|
|
|
|
log.Debug().Msgf("starting network: %+v", network.Name)
|
|
|
|
s.stopWG.Add(1)
|
|
|
|
go func() {
|
|
if err := handler.Run(); err != nil {
|
|
log.Error().Err(err).Msgf("failed to start handler for network %q", network.Name)
|
|
}
|
|
}()
|
|
|
|
s.stopWG.Done()
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *service) StopNetwork(name string) error {
|
|
if handler, found := s.handlers[name]; found {
|
|
handler.Stop()
|
|
log.Debug().Msgf("stopped network: %+v", name)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *service) GetNetworkByID(id int64) (*domain.IrcNetwork, error) {
|
|
network, err := s.repo.GetNetworkByID(id)
|
|
if err != nil {
|
|
log.Error().Err(err).Msgf("failed to get network: %v", id)
|
|
return nil, err
|
|
}
|
|
|
|
channels, err := s.repo.ListChannels(network.ID)
|
|
if err != nil {
|
|
log.Error().Err(err).Msgf("failed to list channels for network %q", network.Server)
|
|
return nil, err
|
|
}
|
|
network.Channels = append(network.Channels, channels...)
|
|
|
|
return network, nil
|
|
}
|
|
|
|
func (s *service) ListNetworks(ctx context.Context) ([]domain.IrcNetwork, error) {
|
|
networks, err := s.repo.ListNetworks(ctx)
|
|
if err != nil {
|
|
log.Error().Err(err).Msgf("failed to list networks: %v", err)
|
|
return nil, err
|
|
}
|
|
|
|
var ret []domain.IrcNetwork
|
|
|
|
for _, n := range networks {
|
|
channels, err := s.repo.ListChannels(n.ID)
|
|
if err != nil {
|
|
log.Error().Msgf("failed to list channels for network %q: %v", n.Server, err)
|
|
return nil, err
|
|
}
|
|
n.Channels = append(n.Channels, channels...)
|
|
|
|
ret = append(ret, n)
|
|
}
|
|
|
|
return ret, nil
|
|
}
|
|
|
|
func (s *service) DeleteNetwork(ctx context.Context, id int64) error {
|
|
network, err := s.GetNetworkByID(id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
log.Debug().Msgf("delete network: %v", id)
|
|
|
|
// Remove network and handler
|
|
if err = s.StopNetwork(network.Name); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err = s.repo.DeleteNetwork(ctx, id); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *service) StoreNetwork(network *domain.IrcNetwork) error {
|
|
if err := s.repo.StoreNetwork(network); err != nil {
|
|
return err
|
|
}
|
|
|
|
log.Debug().Msgf("store network: %+v", network)
|
|
|
|
if network.Channels != nil {
|
|
for _, channel := range network.Channels {
|
|
if err := s.repo.StoreChannel(network.ID, &channel); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
|
|
// stop or start network
|
|
if network.Enabled {
|
|
err := s.startNetwork(*network)
|
|
if err != nil {
|
|
log.Error().Err(err).Msgf("could not start network: %+v", network.Name)
|
|
return fmt.Errorf("could not start network: %v", network.Name)
|
|
}
|
|
|
|
} else {
|
|
err := s.StopNetwork(network.Name)
|
|
if err != nil {
|
|
log.Error().Err(err).Msgf("could not stop network: %+v", network.Name)
|
|
return fmt.Errorf("could not stop network: %v", network.Name)
|
|
}
|
|
}
|
|
|
|
// stop or start network
|
|
//if !network.Enabled {
|
|
// log.Debug().Msgf("stopping network: %+v", network.Name)
|
|
//
|
|
// err := s.StopNetwork(network.Name)
|
|
// if err != nil {
|
|
// log.Error().Err(err).Msgf("could not stop network: %+v", network.Name)
|
|
// return fmt.Errorf("could not stop network: %v", network.Name)
|
|
// }
|
|
//} else {
|
|
// log.Debug().Msgf("starting network: %+v", network.Name)
|
|
//
|
|
// err := s.startNetwork(*network)
|
|
// if err != nil {
|
|
// log.Error().Err(err).Msgf("could not start network: %+v", network.Name)
|
|
// return fmt.Errorf("could not start network: %v", network.Name)
|
|
// }
|
|
//}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *service) StoreChannel(networkID int64, channel *domain.IrcChannel) error {
|
|
if err := s.repo.StoreChannel(networkID, channel); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|