1
0

module.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. package sgnotification
  2. import (
  3. "context"
  4. "encoding/base64"
  5. "strings"
  6. "github.com/sagernet/sing-box/experimental/libbox/platform"
  7. "github.com/sagernet/sing-box/script/jsc"
  8. E "github.com/sagernet/sing/common/exceptions"
  9. "github.com/sagernet/sing/common/logger"
  10. "github.com/sagernet/sing/service"
  11. "github.com/dop251/goja"
  12. )
  13. type SurgeNotification struct {
  14. vm *goja.Runtime
  15. logger logger.Logger
  16. platformInterface platform.Interface
  17. scriptTag string
  18. }
  19. func Enable(vm *goja.Runtime, ctx context.Context, logger logger.Logger) {
  20. platformInterface := service.FromContext[platform.Interface](ctx)
  21. notification := &SurgeNotification{
  22. vm: vm,
  23. logger: logger,
  24. platformInterface: platformInterface,
  25. }
  26. notificationObject := vm.NewObject()
  27. notificationObject.Set("post", notification.js_post)
  28. vm.Set("$notification", notificationObject)
  29. }
  30. func (s *SurgeNotification) js_post(call goja.FunctionCall) goja.Value {
  31. var (
  32. title string
  33. subtitle string
  34. body string
  35. openURL string
  36. clipboard string
  37. mediaURL string
  38. mediaData []byte
  39. mediaType string
  40. autoDismiss int
  41. )
  42. title = jsc.AssertString(s.vm, call.Argument(0), "title", true)
  43. subtitle = jsc.AssertString(s.vm, call.Argument(1), "subtitle", true)
  44. body = jsc.AssertString(s.vm, call.Argument(2), "body", true)
  45. options := jsc.AssertObject(s.vm, call.Argument(3), "options", true)
  46. if options != nil {
  47. action := jsc.AssertString(s.vm, options.Get("action"), "options.action", true)
  48. switch action {
  49. case "open-url":
  50. openURL = jsc.AssertString(s.vm, options.Get("url"), "options.url", false)
  51. case "clipboard":
  52. clipboard = jsc.AssertString(s.vm, options.Get("clipboard"), "options.clipboard", false)
  53. }
  54. mediaURL = jsc.AssertString(s.vm, options.Get("media-url"), "options.media-url", true)
  55. mediaBase64 := jsc.AssertString(s.vm, options.Get("media-base64"), "options.media-base64", true)
  56. if mediaBase64 != "" {
  57. mediaBinary, err := base64.StdEncoding.DecodeString(mediaBase64)
  58. if err != nil {
  59. panic(s.vm.NewGoError(E.Cause(err, "decode media-base64")))
  60. }
  61. mediaData = mediaBinary
  62. mediaType = jsc.AssertString(s.vm, options.Get("media-base64-mime"), "options.media-base64-mime", false)
  63. }
  64. autoDismiss = int(jsc.AssertInt(s.vm, options.Get("auto-dismiss"), "options.auto-dismiss", true))
  65. }
  66. if title != "" && subtitle == "" && body == "" {
  67. body = title
  68. title = ""
  69. } else if title != "" && subtitle != "" && body == "" {
  70. body = subtitle
  71. subtitle = ""
  72. }
  73. var builder strings.Builder
  74. if title != "" {
  75. builder.WriteString("[")
  76. builder.WriteString(title)
  77. if subtitle != "" {
  78. builder.WriteString(" - ")
  79. builder.WriteString(subtitle)
  80. }
  81. builder.WriteString("]: ")
  82. }
  83. builder.WriteString(body)
  84. s.logger.Info("notification: " + builder.String())
  85. if s.platformInterface != nil {
  86. err := s.platformInterface.SendNotification(&platform.Notification{
  87. Identifier: "surge-script-notification-" + s.scriptTag,
  88. TypeName: "Surge Script Notification (" + s.scriptTag + ")",
  89. TypeID: 11,
  90. Title: title,
  91. Subtitle: subtitle,
  92. Body: body,
  93. OpenURL: openURL,
  94. Clipboard: clipboard,
  95. MediaURL: mediaURL,
  96. MediaData: mediaData,
  97. MediaType: mediaType,
  98. Timeout: autoDismiss,
  99. })
  100. if err != nil {
  101. s.logger.Error(E.Cause(err, "send notification"))
  102. }
  103. }
  104. return goja.Undefined()
  105. }