You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
158 lines
4.7 KiB
158 lines
4.7 KiB
package notifications |
|
|
|
import ( |
|
"fmt" |
|
|
|
"github.com/owncast/owncast/models" |
|
"github.com/owncast/owncast/services/config" |
|
"github.com/owncast/owncast/services/notifications/browser" |
|
"github.com/owncast/owncast/services/notifications/discord" |
|
"github.com/owncast/owncast/storage/configrepository" |
|
"github.com/owncast/owncast/storage/data" |
|
"github.com/owncast/owncast/storage/notificationsrepository" |
|
"github.com/pkg/errors" |
|
log "github.com/sirupsen/logrus" |
|
) |
|
|
|
// Notifier is an instance of the live stream notifier. |
|
type Notifier struct { |
|
datastore *data.Store |
|
browser *browser.Browser |
|
discord *discord.Discord |
|
} |
|
|
|
var ( |
|
configRepository = configrepository.Get() |
|
notificationsRepository = notificationsrepository.Get() |
|
) |
|
|
|
// Setup will perform any pre-use setup for the notifier. |
|
func Setup(datastore *data.Store) { |
|
initializeBrowserPushIfNeeded() |
|
} |
|
|
|
func initializeBrowserPushIfNeeded() { |
|
pubKey, _ := configRepository.GetBrowserPushPublicKey() |
|
privKey, _ := configRepository.GetBrowserPushPrivateKey() |
|
|
|
// We need browser push keys so people can register for pushes. |
|
if pubKey == "" || privKey == "" { |
|
browserPrivateKey, browserPublicKey, err := browser.GenerateBrowserPushKeys() |
|
if err != nil { |
|
log.Errorln("unable to initialize browser push notification keys", err) |
|
} |
|
|
|
if err := configRepository.SetBrowserPushPrivateKey(browserPrivateKey); err != nil { |
|
log.Errorln("unable to set browser push private key", err) |
|
} |
|
|
|
if err := configRepository.SetBrowserPushPublicKey(browserPublicKey); err != nil { |
|
log.Errorln("unable to set browser push public key", err) |
|
} |
|
} |
|
|
|
// Enable browser push notifications by default. |
|
if !configRepository.GetHasPerformedInitialNotificationsConfig() { |
|
_ = configRepository.SetBrowserPushConfig(models.BrowserNotificationConfiguration{Enabled: true, GoLiveMessage: config.GetDefaults().FederationGoLiveMessage}) |
|
_ = configRepository.SetHasPerformedInitialNotificationsConfig(true) |
|
} |
|
} |
|
|
|
// New creates a new instance of the Notifier. |
|
func New(datastore *data.Store) (*Notifier, error) { |
|
notifier := Notifier{ |
|
datastore: datastore, |
|
} |
|
|
|
if err := notifier.setupBrowserPush(); err != nil { |
|
log.Error(err) |
|
} |
|
if err := notifier.setupDiscord(); err != nil { |
|
log.Error(err) |
|
} |
|
|
|
return ¬ifier, nil |
|
} |
|
|
|
func (n *Notifier) setupBrowserPush() error { |
|
if configRepository.GetBrowserPushConfig().Enabled { |
|
publicKey, err := configRepository.GetBrowserPushPublicKey() |
|
if err != nil || publicKey == "" { |
|
return errors.Wrap(err, "browser notifier disabled, failed to get browser push public key") |
|
} |
|
|
|
privateKey, err := configRepository.GetBrowserPushPrivateKey() |
|
if err != nil || privateKey == "" { |
|
return errors.Wrap(err, "browser notifier disabled, failed to get browser push private key") |
|
} |
|
|
|
browserNotifier, err := browser.New(n.datastore, publicKey, privateKey) |
|
if err != nil { |
|
return errors.Wrap(err, "error creating browser notifier") |
|
} |
|
n.browser = browserNotifier |
|
} |
|
return nil |
|
} |
|
|
|
func (n *Notifier) notifyBrowserPush() { |
|
destinations, err := notificationsRepository.GetNotificationDestinationsForChannel(BrowserPushNotification) |
|
if err != nil { |
|
log.Errorln("error getting browser push notification destinations", err) |
|
} |
|
for _, destination := range destinations { |
|
unsubscribed, err := n.browser.Send(destination, configRepository.GetServerName(), configRepository.GetBrowserPushConfig().GoLiveMessage) |
|
if unsubscribed { |
|
// If the error is "unsubscribed", then remove the destination from the database. |
|
if err := notificationsRepository.RemoveNotificationForChannel(BrowserPushNotification, destination); err != nil { |
|
log.Errorln(err) |
|
} |
|
} else if err != nil { |
|
log.Errorln(err) |
|
} |
|
} |
|
} |
|
|
|
func (n *Notifier) setupDiscord() error { |
|
discordConfig := configRepository.GetDiscordConfig() |
|
if discordConfig.Enabled && discordConfig.Webhook != "" { |
|
var image string |
|
if serverURL := configRepository.GetServerURL(); serverURL != "" { |
|
image = serverURL + "/logo" |
|
} |
|
discordNotifier, err := discord.New( |
|
configRepository.GetServerName(), |
|
image, |
|
discordConfig.Webhook, |
|
) |
|
if err != nil { |
|
return errors.Wrap(err, "error creating discord notifier") |
|
} |
|
n.discord = discordNotifier |
|
} |
|
return nil |
|
} |
|
|
|
func (n *Notifier) notifyDiscord() { |
|
goLiveMessage := configRepository.GetDiscordConfig().GoLiveMessage |
|
streamTitle := configRepository.GetStreamTitle() |
|
if streamTitle != "" { |
|
goLiveMessage += "\n" + streamTitle |
|
} |
|
message := fmt.Sprintf("%s\n\n%s", goLiveMessage, configRepository.GetServerURL()) |
|
|
|
if err := n.discord.Send(message); err != nil { |
|
log.Errorln("error sending discord message", err) |
|
} |
|
} |
|
|
|
// Notify will fire the different notification channels. |
|
func (n *Notifier) Notify() { |
|
if n.browser != nil { |
|
n.notifyBrowserPush() |
|
} |
|
|
|
if n.discord != nil { |
|
n.notifyDiscord() |
|
} |
|
}
|
|
|