diff --git a/FS.md b/FS.md index e69de29..beb9736 100644 --- a/FS.md +++ b/FS.md @@ -0,0 +1,224 @@ +# **WhspBrd — Functional Requirements** + +## I. **Core Functional Requirements** + +### 1. **Terminal-Based User Interface (TUI)** + +* **Framework**: Use `gocui` for building a rich, responsive text-based UI. +* **Components**: + + * Chat window (scrollable history). + * Contact list / chat list panel. + * Input field for typing messages. + * Status bar with connection/server/user status. + +* **Image Rendering**: + + * Render `.png`, `.jpg`, and `.gif` images in terminal using our own implementation of [Kitty graphics protocol](https://sw.kovidgoyal.net/kitty/graphics-protocol/). + * Display avatars inline next to usernames. + * Display inline images within messages (resizable). + +### 2. **Secure Messaging** + +* **PGP Encryption**: + + * All messages are encrypted locally using the recipient's PGP public key. + * Messages are decrypted only on the receiving client. +* **Message Routing**: + + * Messages are routed through a central server only for delivery. + * Server does **not store** any message content. +* **Offline Message Storage**: + + * Server temporarily caches messages for **offline users** for a configurable TTL (e.g., 12–48 hours). + * If the user does not connect in that window, the message is deleted, and the sender is notified. + +### 3. **Client Data Management** + +* **Local Storage**: + + * All messages are stored client-side in `.json` files per conversation. + * Embedded images are stored as: + + * RGBA raw data in JSON (Base64-encoded). + * A PNG copy in a parallel `media/` folder. +* **PGP Keys**: + + * Each user maintains a local PGP key pair. + * Ability to import/export keys. + * Server can validate keys via a **Web of Trust** model. + +### 4. **Systray & Notifications** + +* **Systray Integration**: + + * Use `getlantern/systray` for showing status icon. + * Show connection status, current server, unread message badge. +* **System Notifications**: + + * Use `beeep` to show toast notifications (cross-platform). + * Trigger on: + + * New message. + * User mentions. + * Connection status changes. + +### 5. **Server Communication** + +* **Server Role**: + + * Acts as a message relay and presence manager. + * Handles identity validation through a Web of Trust. + * Temporary offline message cache (with expiry). +* **Multiple Server Support**: + + * User can connect to multiple servers at once. + * Prioritize closest/fastest server for message delivery. +* **Server Authentication**: + + * Server identifies users via PGP signature. + * No traditional password-based auth. + +### 6. **CLI Messaging Tool (Non-TUI)** + +* Quick command-line utility to send messages: + + ```sh + whspbrd --to user123 --message "hey!" + ``` + +* Designed for shell scripting, automation, cronjobs. +* Uses same encryption and delivery mechanism as TUI. + +--- + +## II. Optional / Extended Functionality + +### 1. **Peer-to-Peer Messaging (Local Network)** + +* **Automatic LAN Discovery**: + + * Bonjour/mDNS or UDP broadcast for peer discovery. +* **Direct LAN Messaging**: + + * If users are in same network, bypass server and send messages directly. + * Messages still encrypted with PGP. +* **Fallback**: If P2P fails, fallback to server-based delivery. + +### 2. **Plugin System (C Modules)** + +* Optional C plugin support. +* Users can write extensions for: + + * UI customization. + * Automation hooks. + * Custom message processors. +* Plugin sandboxing required to maintain app security. + +### 3. **Music Sharing Integration (Linux Only)** + +* Use `playerctl` and `MPRIS` to: + + * Detect current track on Spotify/VLC/etc. + * Optionally share what you're listening to in status. + * Enable `/nowplaying` command to post track in chat. + +--- + +## III. 🔧 Non-Functional Requirements + +### 1. **Cross-Platform Support** + +* Full support for: + + * Linux + * macOS + * Windows (via WSL or native terminal) +* All features should work identically or degrade gracefully. + +### 2. **Performance & Responsiveness** + +* TUI should remain responsive even with long message histories. +* Image rendering must be optimized to avoid lag. + +### 3. **Security** + +* End-to-end encryption by default (no toggle). +* No unencrypted message is ever sent or stored. +* All key exchange and server handshake must be encrypted. + +### 4. **Portability** + +* App should be easy to compile with `go build` on all platforms. +* Minimal external dependencies. + +### 5. **Configurability** + +* Config file in JSON format. +* User can configure: + + * Servers + * Avatar/image size + * Notification preferences + * Logging level + +### 6. **Logging & Debugging** + +* Optional encrypted log file support (for debugging). +* CLI flags like `--verbose`, `--log`, `--debug`. + +--- + +## IV. 📦 Directory and File Structure Example + +```shell +~/.config/whspbrd/ +├── config.json +├── keys/ +│ ├── private.asc +│ └── public.asc +├── messages/ +│ ├── user123.json +│ └── user456.json +├── media/ +│ ├── user123_avatar.png +│ └── msg_img_abc123.png +├── plugins/ +│ └── music_status.so +``` + +--- + +## V. 📌 Example Use Cases + +### 1. TUI Chat + +* Open app from terminal: + + ```sh + whspbrd + ``` + +* Chat using keyboard-driven TUI interface. + +### 2. CLI Send + +* Send message directly from terminal: + + ```sh + whspbrd --to alice --message "Meeting at 5?" + ``` + +### 3. Tray & Notifications + +* App minimized to tray. +* Incoming message triggers `beeep` notification. + +### 4. Local Network P2P + +* Two devices on same Wi-Fi detect each other. +* Chat without routing via server. + +### 5. Plugin Example + +* Load plugin that sends an auto-reply or updates presence from external data. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..cf0a5fa --- /dev/null +++ b/README.md @@ -0,0 +1,24 @@ +# WhspBrd + +- Run main loop, for now + +```shell +go run cmd/tui/main.go +``` + +## File structure + +- may be edited in accordance with [this project standard](https://github.com/golang-standards/project-layout) + +### pkg + +- reusable modules in other projects and used imports, like image manipulation, systray configuration etc... + +### cmd + +- future command line application structure using cobra in cli folder +- tui in tui folder, makes sense huh + +### internal + +- code that is not reusable and we don't want to share it with others, maybe parts of code in cmd will be moved here instead diff --git a/TECH_STACK.md b/TECH_STACK.md index b8e79df..8a94001 100644 --- a/TECH_STACK.md +++ b/TECH_STACK.md @@ -3,15 +3,30 @@ ## GO - Klient aplikace pro uživatele a komunikace se serverem -- - vizuální stránka aplikace, nejde rendrovat obrázky -- - vizuální stránka aplikace -- - rendrování obrázků v terminálu +- - vizuální stránka aplikace JOO +- - rendrování obrázků v terminálu NEE, napsali jsme vlastní (profilové obrázky nebo posílané médium) +- - systray pro windows, linux, i macos +- - image editing NEEE, nepotřebujeme actually +- - notifikace an windows i linux ## C - Pro rendrování a hashovací algoritmy v klient aplikaci embeded v go kodu -## Java +## Java? - Server pro komunikaci mezi uživateli + +## Magick pro změnu obrázků + +- resize pro obrázky na 2 řádkovou resolution convert output.png\ + \( +clone -alpha extract\ + -draw 'fill black polygon 0,0 0,15 15,0 fill white circle 15,15 15,0'\ + \( +clone -flip \) -compose Multiply -composite\ + \( +clone -flop \) -compose Multiply -composite\ + \) -alpha off -compose CopyOpacity -composite kogami-rounded.png + +## Nápady + +- načítat a sdílet přehrávanou hudbu (discord spotify integration, but with playerctl or some other music protocol) diff --git a/configs/config.json b/configs/config.json new file mode 100644 index 0000000..e69de29 diff --git a/configs/servers/default/server.json b/configs/servers/default/server.json new file mode 100644 index 0000000..e69de29 diff --git a/configs/servers/default/users/alice/alice.pub b/configs/servers/default/users/alice/alice.pub new file mode 100644 index 0000000..e69de29 diff --git a/configs/servers/default/users/alice/messages.json b/configs/servers/default/users/alice/messages.json new file mode 100644 index 0000000..e69de29 diff --git a/configs/servers/default/users/bob/bob.pub b/configs/servers/default/users/bob/bob.pub new file mode 100644 index 0000000..e69de29 diff --git a/configs/servers/default/users/bob/messages.json b/configs/servers/default/users/bob/messages.json new file mode 100644 index 0000000..e69de29 diff --git a/go.mod b/go.mod index c030e61..53f187a 100644 --- a/go.mod +++ b/go.mod @@ -3,9 +3,9 @@ module whspbrd go 1.24.2 require ( - github.com/dolmen-go/kittyimg v0.0.0-20250507221057-648811cc98ed github.com/getlantern/systray v1.2.2 github.com/jroimartin/gocui v0.5.0 + golang.org/x/sys v0.30.0 ) require github.com/rivo/uniseg v0.4.7 // indirect @@ -21,5 +21,4 @@ require ( github.com/mattn/go-runewidth v0.0.16 // indirect github.com/nsf/termbox-go v1.1.1 // indirect github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c // indirect - golang.org/x/sys v0.30.0 // indirect ) diff --git a/go.sum b/go.sum index 92ca8d1..b70c8e6 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,5 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dolmen-go/kittyimg v0.0.0-20250507221057-648811cc98ed h1:kDKSQ5o62eFce2771pkdTu6kjv4I3s5dFhe6gXgSeUg= -github.com/dolmen-go/kittyimg v0.0.0-20250507221057-648811cc98ed/go.mod h1:2vk7ATPVcI7uW4Sh6PrSQvtO+Czmq8509xcg/y8Osd0= github.com/getlantern/context v0.0.0-20190109183933-c447772a6520 h1:NRUJuo3v3WGC/g5YiyF790gut6oQr5f3FBI88Wv0dx4= github.com/getlantern/context v0.0.0-20190109183933-c447772a6520/go.mod h1:L+mq6/vvYHKjCX2oez0CgEAJmbq1fbb/oNJIWQkBybY= github.com/getlantern/errors v0.0.0-20190325191628-abdb3e3e36f7 h1:6uJ+sZ/e03gkbqZ0kUG6mfKoqDb4XMAzMIwlajq19So= diff --git a/pkg/resize_image/resize_image.go b/pkg/resize_image/resize_image.go index ccd236f..fdfb7b9 100644 --- a/pkg/resize_image/resize_image.go +++ b/pkg/resize_image/resize_image.go @@ -6,13 +6,20 @@ import ( ) func Resize(img image.RGBA, width int, height int) (*image.RGBA, error) { - if width <= 0 || height <= 0 { + originalWidth := img.Bounds().Dx() + originalHeight := img.Bounds().Dy() + + if width <= 0 && height <= 0 { return nil, nil + } else if width <= 0 { + width = int(float64(height) * float64(originalWidth) / float64(originalHeight)) + } else if height <= 0 { + height = int(float64(width) * float64(originalHeight) / float64(originalWidth)) } newImg := image.NewRGBA(image.Rect(0, 0, width, height)) - scaleX := float64(img.Bounds().Dx()) / float64(width) - scaleY := float64(img.Bounds().Dy()) / float64(height) + scaleX := float64(originalWidth) / float64(width) + scaleY := float64(originalHeight) / float64(height) for y := 0; y < height; y++ { for x := 0; x < width; x++ { diff --git a/shell.nix b/shell.nix index d5946e3..ba0cebc 100644 --- a/shell.nix +++ b/shell.nix @@ -7,9 +7,12 @@ in webkitgtk openssl libayatana-appindicator + #imagemagickBig ]; nativeBuildInputs = with pkgs; [ pkg-config ]; dbus = pkgs.dbus; + + #PKG_CONFIG_PATH = "${pkgs.imagemagickBig.dev}/lib/pkgconfig"; }