mpris added
This commit is contained in:
parent
4cb67f0a17
commit
426e088c43
@ -6,6 +6,12 @@
|
|||||||
go run cmd/main.go
|
go run cmd/main.go
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- Run on nix
|
||||||
|
|
||||||
|
```shell
|
||||||
|
nix run git+https://git.foglar.tech/foglar/WhspBrd.git
|
||||||
|
```
|
||||||
|
|
||||||
## File structure
|
## File structure
|
||||||
|
|
||||||
- may be edited in accordance with [this project standard](https://github.com/golang-standards/project-layout)
|
- may be edited in accordance with [this project standard](https://github.com/golang-standards/project-layout)
|
||||||
|
|||||||
40
_examples/mpris.go
Normal file
40
_examples/mpris.go
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"whspbrd/pkg/mpris"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
players, err := mpris.Mpris()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, p := range players {
|
||||||
|
fmt.Printf("Player: %s\n", p.Name)
|
||||||
|
fmt.Printf("Title : %s\n", p.Title)
|
||||||
|
if len(p.Artist) > 0 {
|
||||||
|
fmt.Printf("Artist: %s\n", p.Artist[0])
|
||||||
|
}
|
||||||
|
fmt.Printf("Album : %s\n", p.Album)
|
||||||
|
|
||||||
|
if p.ArtURL != "" {
|
||||||
|
if mpris.IsRemoteArt(p.ArtURL) {
|
||||||
|
fmt.Printf("Remote artwork found: %s\n", p.ArtURL)
|
||||||
|
err := mpris.DownloadArt(p.ArtURL, p.Name+"_art.jpg")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error downloading art: %v\n", err)
|
||||||
|
} else {
|
||||||
|
fmt.Printf("Artwork saved as %s_art.jpg\n", p.Name)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fmt.Printf("Local artwork: %s\n", p.ArtURL)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fmt.Println("Artwork: not available")
|
||||||
|
}
|
||||||
|
fmt.Println()
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -20,6 +20,13 @@
|
|||||||
"receiver": "Filip",
|
"receiver": "Filip",
|
||||||
"content": "VG8gYnljaG9tIG1vaGxpLCB2eWhvdnVqZSB0aSB0ZW5obGUgdMO9ZGVuIHZlIHN0xZllZHU/Cg==",
|
"content": "VG8gYnljaG9tIG1vaGxpLCB2eWhvdnVqZSB0aSB0ZW5obGUgdMO9ZGVuIHZlIHN0xZllZHU/Cg==",
|
||||||
"timestamp": "2024-10-01T11:23:00Z"
|
"timestamp": "2024-10-01T11:23:00Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "4",
|
||||||
|
"sender": "Bob",
|
||||||
|
"receiver": "Filip",
|
||||||
|
"content": "TmVibyB2ZSDEjXR2cnRlawo=",
|
||||||
|
"timestamp": "2024-10-01T11:24:00Z"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
65
docs/TODO.md
Normal file
65
docs/TODO.md
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
# Tasks to be done
|
||||||
|
|
||||||
|
## TUI
|
||||||
|
|
||||||
|
- [ ] Initial configuration setup
|
||||||
|
- [ ] Solve colors issue
|
||||||
|
- [ ] Complete chat loading and sending messages to contacts so it is written to the file
|
||||||
|
- [ ] Create systray
|
||||||
|
- [ ] Share what music am i listening using mpris
|
||||||
|
|
||||||
|
### Chat
|
||||||
|
|
||||||
|
- [ ] Add scrolling capability
|
||||||
|
- [ ] Solve multiline messages and resizing the window
|
||||||
|
- [ ] Implement calculating positions of images and profile pictures
|
||||||
|
- [ ] Add rendering image previews
|
||||||
|
- [ ] Render image in chat
|
||||||
|
- [ ] Render image in chat with scroll
|
||||||
|
- [ ] Add rendering profile pictures
|
||||||
|
- [ ] Solve too long message history problem - render only first 100 messages?
|
||||||
|
- [ ] Check chat without images, if kitty image protocol is not used
|
||||||
|
- [ ] Check chat on windows
|
||||||
|
- [ ] Create timestamps like today yesterday etc...
|
||||||
|
|
||||||
|
### Sidebar
|
||||||
|
|
||||||
|
- [ ] Profile pictures next to the username
|
||||||
|
- [ ] Ability to scroll through users and rerender profile images
|
||||||
|
- [ ] Colors maybe?
|
||||||
|
- [ ] Solve too long names and window width
|
||||||
|
|
||||||
|
### Input
|
||||||
|
|
||||||
|
- [ ] Add emoji internal selector
|
||||||
|
- [ ] Add button to add attachement
|
||||||
|
- [ ] Add correct parsing of input to correct chat
|
||||||
|
|
||||||
|
### Profile Sidebar
|
||||||
|
|
||||||
|
- [ ] Profile image
|
||||||
|
- [ ] Mpris integration
|
||||||
|
|
||||||
|
## CMD
|
||||||
|
|
||||||
|
- [ ] Create basic commands template to use chat from commandline
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
- [ ] Keybindings for application
|
||||||
|
- [ ] IDs instead of usernames
|
||||||
|
- [ ] Load and Write new messages to the files
|
||||||
|
- [ ] Change preloading of Contacts from list to complex structure
|
||||||
|
- [ ] Change preloading of messages from list to complex structure
|
||||||
|
- [ ] Add new contact
|
||||||
|
- [ ] Choose server to use when running TUI
|
||||||
|
- [ ] Create colorthemes
|
||||||
|
- [ ] Add reactions to messages and replies
|
||||||
|
|
||||||
|
## Server
|
||||||
|
|
||||||
|
## Communication
|
||||||
|
|
||||||
|
## IDEAS
|
||||||
|
|
||||||
|
- just set window size of the box to be even, so there should not be need in rendering half of the profile picture
|
||||||
2
go.mod
2
go.mod
@ -3,6 +3,8 @@ module whspbrd
|
|||||||
go 1.24.2
|
go 1.24.2
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/Endg4meZer0/go-mpris v1.0.5
|
||||||
|
github.com/godbus/dbus/v5 v5.1.0
|
||||||
github.com/jroimartin/gocui v0.5.0
|
github.com/jroimartin/gocui v0.5.0
|
||||||
golang.org/x/sys v0.30.0
|
golang.org/x/sys v0.30.0
|
||||||
)
|
)
|
||||||
|
|||||||
5
go.sum
5
go.sum
@ -1,3 +1,8 @@
|
|||||||
|
github.com/Endg4meZer0/go-mpris v1.0.5 h1:a3FUGD/h3tQAFlcl/YH4TVwtI/NVm4UJAGMEyaKai7I=
|
||||||
|
github.com/Endg4meZer0/go-mpris v1.0.5/go.mod h1:eh//AAqSR5XF4G2mAKe9NrSp5sH8G6f3RnYzbupi8tU=
|
||||||
|
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
|
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
|
||||||
|
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
github.com/jroimartin/gocui v0.5.0 h1:DCZc97zY9dMnHXJSJLLmx9VqiEnAj0yh0eTNpuEtG/4=
|
github.com/jroimartin/gocui v0.5.0 h1:DCZc97zY9dMnHXJSJLLmx9VqiEnAj0yh0eTNpuEtG/4=
|
||||||
github.com/jroimartin/gocui v0.5.0/go.mod h1:l7Hz8DoYoL6NoYnlnaX6XCNR62G7J5FfSW5jEogzaxE=
|
github.com/jroimartin/gocui v0.5.0/go.mod h1:l7Hz8DoYoL6NoYnlnaX6XCNR62G7J5FfSW5jEogzaxE=
|
||||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||||
|
|||||||
@ -66,8 +66,6 @@ func (p Palette) Underlined(c Color) string { return c.Underline() } // convenie
|
|||||||
func (p Palette) Text(c Color) string { return c.Text() }
|
func (p Palette) Text(c Color) string { return c.Text() }
|
||||||
|
|
||||||
var Colors = Palette{
|
var Colors = Palette{
|
||||||
// I kept the numeric values that you originally used in your map so behavior stays the same.
|
|
||||||
// If you'd rather map them to "standard" 30..37 and 90..97 codes, change the integers here.
|
|
||||||
Base00: NewColor(31),
|
Base00: NewColor(31),
|
||||||
Base01: NewColor(32),
|
Base01: NewColor(32),
|
||||||
Base02: NewColor(33),
|
Base02: NewColor(33),
|
||||||
|
|||||||
95
pkg/mpris/mpris.go
Normal file
95
pkg/mpris/mpris.go
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
package mpris
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/Endg4meZer0/go-mpris"
|
||||||
|
"github.com/godbus/dbus/v5"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PlayerInfo struct {
|
||||||
|
Name string
|
||||||
|
Title string
|
||||||
|
Artist []string
|
||||||
|
Album string
|
||||||
|
ArtURL string
|
||||||
|
}
|
||||||
|
|
||||||
|
func Mpris() ([]PlayerInfo, error) {
|
||||||
|
conn, err := dbus.SessionBus()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
names, err := mpris.List(conn)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(names) == 0 {
|
||||||
|
return nil, fmt.Errorf("no MPRIS players found")
|
||||||
|
}
|
||||||
|
|
||||||
|
var players []PlayerInfo
|
||||||
|
for _, name := range names {
|
||||||
|
player := mpris.New(conn, name)
|
||||||
|
|
||||||
|
metadata, err := player.GetMetadata()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
title, _ := metadata["xesam:title"].Value().(string)
|
||||||
|
artist, _ := metadata["xesam:artist"].Value().([]string)
|
||||||
|
album, _ := metadata["xesam:album"].Value().(string)
|
||||||
|
|
||||||
|
var artURL string
|
||||||
|
if val, ok := metadata["mpris:artUrl"]; ok {
|
||||||
|
if url, ok := val.Value().(string); ok {
|
||||||
|
artURL = url
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
players = append(players, PlayerInfo{
|
||||||
|
Name: name,
|
||||||
|
Title: title,
|
||||||
|
Artist: artist,
|
||||||
|
Album: album,
|
||||||
|
ArtURL: artURL,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return players, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsRemoteArt(uri string) bool {
|
||||||
|
return strings.HasPrefix(uri, "http://") || strings.HasPrefix(uri, "https://")
|
||||||
|
}
|
||||||
|
|
||||||
|
func DownloadArt(url, dest string) error {
|
||||||
|
resp, err := http.Get(url)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to fetch art: %w", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
return fmt.Errorf("bad status: %s", resp.Status)
|
||||||
|
}
|
||||||
|
|
||||||
|
out, err := os.Create(dest)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create file: %w", err)
|
||||||
|
}
|
||||||
|
defer out.Close()
|
||||||
|
|
||||||
|
_, err = io.Copy(out, resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to save art: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user