diff options
| author | Caroline Larimore <caroline@larimo.re> | 2025-01-30 16:39:09 -0800 |
|---|---|---|
| committer | Caroline Larimore <caroline@larimo.re> | 2025-01-30 16:39:09 -0800 |
| commit | 784ee51b9613cac5764c9a33c343655e514e20f0 (patch) | |
| tree | d6291c6c2a6be604913952f529cc335e827473c9 /server.go | |
Initial Commit
Diffstat (limited to 'server.go')
| -rw-r--r-- | server.go | 133 |
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 +} |