aboutsummaryrefslogtreecommitdiff
path: root/server.go
diff options
context:
space:
mode:
authorCaroline Larimore <caroline@larimo.re>2025-01-30 16:39:09 -0800
committerCaroline Larimore <caroline@larimo.re>2025-01-30 16:39:09 -0800
commit784ee51b9613cac5764c9a33c343655e514e20f0 (patch)
treed6291c6c2a6be604913952f529cc335e827473c9 /server.go
Initial Commit
Diffstat (limited to 'server.go')
-rw-r--r--server.go133
1 files changed, 133 insertions, 0 deletions
diff --git a/server.go b/server.go
new file mode 100644
index 0000000..9b94f70
--- /dev/null
+++ b/server.go
@@ -0,0 +1,133 @@
+package main
+
+import (
+ "image"
+ "image/png"
+ "log"
+ "os"
+ "strings"
+ "time"
+
+ "github.com/godbus/dbus/v5"
+)
+
+type server struct{}
+
+func (s server) GetCapabilities() (capabilities []string, e *dbus.Error) {
+ // log.Print("GetCapabilities called")
+ return []string{
+ "body",
+ "actions",
+ }, nil
+}
+
+func (s server) GetServerInformation() (name, vendor, version, specVersion string, e *dbus.Error) {
+ // log.Print("GetServerInformation called")
+ return "corvid", "CartConnoisseur", "0.1.0", "1.2", nil
+}
+
+func (s server) CloseNotification(id uint32) (e *dbus.Error) {
+ // log.Printf("CloseNotification called: %d", id)
+ notification, ok := notifications.notifications[id]
+ if ok {
+ notification.close(CloseReasonClosed)
+ }
+
+ return nil
+}
+
+func (s server) Notify(appName string, replacesId uint32, appIcon string, summary string, body string, actions []string, hints map[string]dbus.Variant, expireTimeout int32) (id uint32, e *dbus.Error) {
+ // log.Print("Notify called")
+ notifications.mutex.Lock()
+ defer notifications.mutex.Unlock()
+
+ if replacesId == 0 {
+ id = notifications.nextId
+ notifications.nextId++
+ } else {
+ id = replacesId
+ }
+
+ actionMap := make(map[string]string)
+ for i := 0; i < len(actions)-1; i += 2 {
+ actionMap[actions[i]] = actions[i+1]
+ }
+
+ hintMap := make(map[string]hint)
+ img := ""
+
+ for key, value := range hints {
+ if !value.Signature().Empty() {
+ if strings.Contains("ybnqiuxtds", string(value.Signature().String()[0])) {
+ hintMap[key] = hint{Variant: value}
+ } else if key == "image-data" {
+ raw := value.Value().([]interface{})
+
+ var i image.Image
+ if raw[3].(bool) {
+ i = &image.NRGBA{
+ Pix: raw[6].([]uint8),
+ Stride: int(raw[2].(int32)),
+ Rect: image.Rect(0, 0, int(raw[0].(int32)), int(raw[1].(int32))),
+ }
+ } else {
+ rgb := raw[6].([]uint8)
+ rgba := make([]uint8, len(rgb)/3*4)
+
+ for i := 0; i < len(rgb)-1; i += 3 {
+ rgba[i/3*4] = rgb[i]
+ rgba[i/3*4+1] = rgb[i+1]
+ rgba[i/3*4+2] = rgb[i+2]
+ rgba[i/3*4+3] = 0xff
+ }
+
+ i = &image.NRGBA{
+ Pix: rgba,
+ Stride: int(raw[2].(int32)),
+ Rect: image.Rect(0, 0, int(raw[0].(int32)), int(raw[1].(int32))),
+ }
+ }
+ _ = i
+
+ f, err := os.CreateTemp(os.TempDir(), "corvid-*.png")
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer f.Close()
+
+ png.Encode(f, i)
+
+ img = f.Name()
+ }
+ }
+ }
+
+ if expireTimeout == -1 {
+ expireTimeout = DEFAULT_EXPIRATION
+ }
+
+ notification := notification{
+ Id: id,
+ AppName: appName,
+ AppIcon: appIcon,
+ Summary: summary,
+ Body: body,
+ Actions: actionMap,
+ Hints: hintMap,
+ Timestamp: time.Now().Unix(),
+ Expiration: expireTimeout,
+ Image: img,
+ timer: nil,
+ }
+
+ if expireTimeout != 0 {
+ notification.timer = time.AfterFunc(time.Duration(expireTimeout)*time.Millisecond, func() {
+ notification.close(CloseReasonExpire)
+ })
+ }
+
+ notifications.notifications[id] = notification
+ output()
+
+ return id, nil
+}