browser.go 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. package browser
  2. import (
  3. "encoding/json"
  4. "github.com/SherClockHolmes/webpush-go"
  5. "github.com/owncast/owncast/core/data"
  6. "github.com/pkg/errors"
  7. )
  8. // Browser is an instance of the Browser service.
  9. type Browser struct {
  10. datastore *data.Datastore
  11. privateKey string
  12. publicKey string
  13. }
  14. // New will create a new instance of the Browser service.
  15. func New(datastore *data.Datastore, publicKey, privateKey string) (*Browser, error) {
  16. return &Browser{
  17. datastore: datastore,
  18. privateKey: privateKey,
  19. publicKey: publicKey,
  20. }, nil
  21. }
  22. // GenerateBrowserPushKeys will create the VAPID keys required for web push notifications.
  23. func GenerateBrowserPushKeys() (string, string, error) {
  24. privateKey, publicKey, err := webpush.GenerateVAPIDKeys()
  25. if err != nil {
  26. return "", "", errors.Wrap(err, "error generating web push keys")
  27. }
  28. return privateKey, publicKey, nil
  29. }
  30. // Send will send a browser push notification to the given subscription.
  31. func (b *Browser) Send(
  32. subscription string,
  33. title string,
  34. body string,
  35. ) (bool, error) {
  36. type message struct {
  37. Title string `json:"title"`
  38. Body string `json:"body"`
  39. Icon string `json:"icon"`
  40. }
  41. m := message{
  42. Title: title,
  43. Body: body,
  44. Icon: "/logo/external",
  45. }
  46. d, err := json.Marshal(m)
  47. if err != nil {
  48. return false, errors.Wrap(err, "error marshalling web push message")
  49. }
  50. // Decode subscription
  51. s := &webpush.Subscription{}
  52. if err := json.Unmarshal([]byte(subscription), s); err != nil {
  53. return false, errors.Wrap(err, "error decoding destination subscription")
  54. }
  55. // Send Notification
  56. resp, err := webpush.SendNotification(d, s, &webpush.Options{
  57. VAPIDPublicKey: b.publicKey,
  58. VAPIDPrivateKey: b.privateKey,
  59. Topic: "owncast-go-live",
  60. TTL: 120,
  61. // Not really the subscriber, but a contact point for the sender.
  62. Subscriber: "owncast@owncast.online",
  63. })
  64. if resp.StatusCode == 410 {
  65. return true, nil
  66. } else if err != nil {
  67. return false, errors.Wrap(err, "error sending browser push notification")
  68. }
  69. defer resp.Body.Close()
  70. return false, err
  71. }