• Stars
    star
    234
  • Rank 171,630 (Top 4 %)
  • Language
    Rust
  • License
    Apache License 2.0
  • Created over 2 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A dead simple notification daemon 🦡

Desktop notifications are small, passive popup dialogs that notify the user of particular events in an asynchronous manner. These passive popups can automatically disappear after a short period of time.

runst is the server implementation of freedesktop.org - Desktop Notifications Specification and it can be used to receive notifications from applications via D-Bus. As of now, only X11 is supported.

Features

  • Fully customizable notification window (size, location, text, colors).
  • Template-powered (Jinja2/Django) notification text.
  • Auto-clear notifications based on a fixed time or estimated read time.
  • Run custom OS commands based on the matched notifications.

Roadmap

runst is initially designed to show a simple notification window. On top of that, it combines customization-oriented and semi-innovative features. In the future, I'm aiming to shape runst functionality based on new ideas and feedback.

Feel free to submit an issue if you have something in mind or having a problem!

Installation

From crates.io

runst can be installed from crates.io:

$ cargo install runst

The minimum supported Rust version is 1.70.0.

Arch Linux

runst can be installed from the extra repository using pacman:

$ pacman -S runst

Or you can install the available AUR packages with using an AUR helper. For example:

$ paru -S runst-git

Alpine Linux

runst is available for Alpine Edge. It can be installed via apk after enabling the testing repository.

apk add runst

Binary releases

See the available binaries for different operating systems/architectures from the releases page.

Release tarballs are signed with the following PGP key: AEF8C7261F4CEB41A448CBC41B250A9F78535D1A

Build from source

Prerequisites

Instructions

  1. Clone the repository.
$ git clone https://github.com/orhun/runst && cd runst/
  1. Build.
$ CARGO_TARGET_DIR=target cargo build --release

Binary will be located at target/release/runst.

Usage

On Xorg startup

You can use xinitrc or xprofile for autostarting runst.

xinitrc

If you are starting Xorg manually with xinit, you can runst on X server startup via xinitrc:

$HOME/.xinitrc:

runst &

Long-running programs such as notification daemons should be started before the window manager, so they should either fork themself or be run in the background via appending & sign. Otherwise, the script would halt and wait for each program to exit before executing the window manager or desktop environment.

In the case of runst not being available since it's started at a faster manner than the window manager, you can add a delay as shown in the example below:

{ sleep 2; runst; } &

xprofile

If you are using a display manager, you can utilize an xprofile file which allows you to execute commands at the beginning of the X user session.

The xprofile file, which is ~/.xprofile or /etc/xprofile, can be styled similarly to xinitrc.

As a D-Bus service

You can create a D-Bus service to launch runst automatically on the first notification action. For example, you can create the following service configuration:

/usr/share/dbus-1/services/org.orhun.runst.service:

[D-BUS Service]
Name=org.freedesktop.Notifications
Exec=/usr/bin/runst

Whenever an application sends a notification by sending a signal to org.freedesktop.Notifications, D-Bus activates runst.

Also, see #1 for systemd integration.

Commands

runst can be controlled with sending commands to D-Bus via dbus-send(1).

dbus-send --print-reply --dest=org.freedesktop.Notifications /org/freedesktop/Notifications/ctl "org.freedesktop.Notifications.${command}"

Available commands are:

  • History: show the last notification.
  • Close: close the notification.
  • CloseAll: close all the notifications.

For example:

# show the last notification
dbus-send --print-reply \
          --dest=org.freedesktop.Notifications \
          /org/freedesktop/Notifications/ctl \
          org.freedesktop.Notifications.History

An example usage for i3:

# Notification history
bindsym $mod+grave exec dbus-send --print-reply \
        --dest=org.freedesktop.Notifications /org/freedesktop/Notifications/ctl org.freedesktop.Notifications.History

# Close notification
bindsym $mod+shift+grave exec dbus-send --print-reply \
        --dest=org.freedesktop.Notifications /org/freedesktop/Notifications/ctl org.freedesktop.Notifications.Close

Additionally, to view the server version:

dbus-send --print-reply --dest=org.freedesktop.Notifications /org/freedesktop/Notifications org.freedesktop.Notifications.GetServerInformation

Configuration

runst configuration file supports TOML format and the default configuration values can be found here.

If exists, configuration file is read from the following default locations:

  • $HOME/.config/runst/runst.toml
  • $HOME/.runst/runst.toml

You can also specify a path via RUNST_CONFIG environment variable.

Global configuration

log_verbosity

Sets the logging verbosity. Possible values are error, warn, info, debug and trace.

startup_notification

Shows a notification at startup if set to true.

geometry

Sets the window geometry. The value format is <width>x<height>+<x>+<y>.

For setting this value, I recommend using a tool like slop which helps with querying for a selection and printing the region to stdout.

wrap_content

If set to true, the window is resized to match the contents.

If the content is larger than the window size, geometry option is used for maximum width and height.

font

Sets the font to use for the window.

template

Sets the template for the notification message. The syntax is based on Jinja2 and Django templates.

Simply, there are 3 kinds of delimiters:

  • {{ and }} for expressions
  • {% or {%- and %} or -%} for statements
  • {# and #} for comments

See Tera documentation for more information about control structures, built-in filters, etc.

Context

Context is the model that holds the required data for template rendering. The JSON format is used in the following example for the representation of a context.

{
  "app_name": "runst",
  "summary": "example",
  "body": "this is a notification 🦡",
  "urgency": "normal",
  "unread_count": 1,
  "timestamp": 1672426610
}
Styling

Pango is used for text rendering. The markup documentation can be found here.

A few examples would be:

  • <b>bold text</b>: bold text
  • <span foreground="blue">blue text</span>: blue text
  • <tt>monospace text</tt>: monospace text

Urgency configuration

There are 3 levels of urgency defined in the Freedesktop specification and they define the importance of the notification.

  1. low: e.g. "joe signed on"
  2. normal: e.g. "you got mail"
  3. critical: e.g. "your computer is on fire!"

You can configure runst to act differently based on these urgency levels. For this, there need to be 3 different sections defined in the configuration file. Each of these sections has the following fields:

[urgency_{level}] # urgency_low, urgency_normal or urgency_critical
    background = "#000000" # background color
    foreground = "#ffffff" # foreground color
    timeout = 10
    auto_clear = true
    text = "normal"
    custom_commands = []

timeout

This is the default timeout value (in seconds) if the notification has no timeout specified by the sender. If the timeout is 0, the notification is not automatically closed (i.e. it never expires).

auto_clear

If set to true, the estimated read time of the notification is calculated and it is used as the timeout. This is useful if you want the notifications to disappear as you finish reading them.

text

This is the custom text for the urgency level and can be used in template context as urgency. If it is not set, the corresponding urgency level is used (e.g. "low", "normal" or "critical").

custom_commands

With using this option, you can run custom OS commands based on urgency levels and the notification contents. The basic usage is the following:

custom_commands = [
    { command = 'echo "{{app_name}} {{summary}} {{body}}"' } # echoes the notification to stdout
]

As shown in the example above, you can specify an arbitrary command via command which is also processed through the template engine. This means that you can use the same template context.

The filtering is done by matching the fields in JSON via using filter along with the command. For example, if you want to play a custom notification sound for a certain application:

custom_commands = [
  { filter = '{ "app_name":"notify-send" }', command = 'aplay notification.wav' },
  { filter = '{ "app_name":"weechat" }', command = 'aplay irc.wav' }
]

The JSON filter can have the following fields:

  • app_name: Name of the application that sends the notification.
  • summary: Summary of the notification.
  • body: Body of the notification.

Each of these fields is matched using regex and you can combine them as follows:

custom_commands = [
  { filter = '{ "app_name":"telegram|discord|.*chat$","body":"^hello.*" }', command = 'gotify push -t "{{app_name}}" "someone said hi!"' }
]

In this hypothetical example, we are sending a Gotify notification when someone says hi to us in any chatting application matched by the regex.

Why this exists?

I have been a user of dunst for a long time. However, they made some uncool breaking changes in v1.7.0 and it completely broke my configuration. That day, I refused to update dunst (I was too lazy to re-configure) and decided to write my own notification server using Rust.

I wanted to keep runst simple since the way I use dunst was really simple. I was only showing an overlay window on top of i3status as shown below:

runst use case

And that's how runst is born.

Similar projects

License

Licensed under either of Apache License Version 2.0 or The MIT License at your option.

Copyright © 2022-2023, Orhun Parmaksız

More Repositories

1

git-cliff

A highly customizable Changelog Generator that follows Conventional Commit specifications ⛰️
Rust
5,800
star
2

kmon

Linux Kernel Manager and Activity Monitor 🐧💻
Rust
1,911
star
3

systeroid

A more powerful alternative to sysctl(8) with a terminal user interface 🐧
Rust
997
star
4

gpg-tui

Manage your GnuPG keys with ease! 🔐
Rust
991
star
5

rustypaste

A minimal file upload/pastebin service.
Rust
757
star
6

halp

A CLI tool to get help with CLI tools 🐙
Rust
597
star
7

menyoki

Screen{shot,cast} and perform ImageOps on the command line 🌱 🏞️
Rust
489
star
8

linuxwave

Generate music from the entropy of Linux 🐧🎵
Zig
399
star
9

pkgtop

Interactive package manager and resource monitor designed for the GNU/Linux.
Go
268
star
10

zps

A small utility for listing and reaping zombie processes on GNU/Linux.
C
153
star
11

CoolModFiles

A web player that plays some cool MOD files randomly 🎶
JavaScript
132
star
12

kermit

A VTE-based, simple and froggy terminal emulator 🐸
C
114
star
13

rust-tui-template

A template for bootstrapping a Rust TUI application with tui-rs & crossterm
Rust
77
star
14

dotfiles

Orhun's Arch Linux configuration files and scripts 🏠
Shell
70
star
15

godsays

Rust port of the Terry Davis' (RIP) "god says" program
Rust
69
star
16

rtl_map

FFT-based visualizer for RTL-SDR devices. (RTL2832/DVB-T)
C
67
star
17

battleship-rs

Battleship game implemented in Rust
Rust
65
star
18

git-cliff-action

GitHub action to generate a changelog based on the Git history
Shell
65
star
19

rustypaste-cli

A CLI tool for rustypaste
Rust
56
star
20

k3pler

Android network connection blocker and packet analyzer built on top of local HTTP proxy.
Java
48
star
21

orhun

My GitHub profile README.md ⭐:octocat:
41
star
22

ApkServInject

Tool for injecting (smali) services to APK files
Java
30
star
23

cargo-nocode

Cargo subcommand to easily bootstrap nocode applications. Write nothing; deploy nowhere.
Rust
29
star
24

god

Linux utility for simplifying the Git usage.
Go
25
star
25

dnsleaktest-tui

A proof-of-concept TUI for testing DNS leaks & running traceroute
Rust
20
star
26

PSAUX

Android task manager and automated background service killer.
Java
20
star
27

alpkg

Set up Alpine Linux packaging environment with a breeze! 🏔
Shell
18
star
28

packaging-rust-for-npm

https://blog.orhun.dev/packaging-rust-for-npm/
JavaScript
17
star
29

Picasso

PIC16F877A based 5V/20MHz development board and PIC programmer
C
15
star
30

PKGBUILDs

Arch Linux packages that I maintain 🔧
Shell
13
star
31

personal-blog

The source of my blog ✍🏼
SCSS
13
star
32

dialogflowbot

Google's Dialogflow implementation on Android with additional features.
Java
11
star
33

i3-workspace-brightness

Utility to auto-adjust the brightness of i3wm workspaces
Rust
11
star
34

Black-Waves

A wavy dark theme for VSCode
10
star
35

HydropotX

Automated and Self-contained Hydroponics System 🌱
Kotlin
9
star
36

advent-of-code

My Advent of Code solutions 🐢
Rust
8
star
37

Last-Commit

A VSCode extension that focuses on the last git commit
JavaScript
7
star
38

zig-http-benchmarks

Benchmarking Zig HTTP client against Rust, Go, Python and curl
Zig
6
star
39

binsider

Analyze ELF binaries like a boss (WIP)
Rust
4
star
40

orhun.github.io

Personal website
HTML
4
star
41

theattyr

A terminal theatre for playing VT100 art and animations
Rust
4
star
42

godsings

https://melody.godsays.xyz
Python
3
star
43

base16-kermit

Base16 for kermit
Mustache
3
star
44

parseit

A simple text file parsing library powered by regex and glob patterns
Rust
3
star
45

typewriter

Turn your keyboard into a typewriter (WIP)
Rust
2
star
46

firebox-auth-cracker

A CLI tool to brute force the authentication signature of WatchGuard's Firebox
Rust
2
star
47

playfair-rs

Playfair cipher implemented in Rust
Rust
2
star
48

rust-arch-lto

Rust + ABS + LTO = 🤯 (PoC)
Shell
1
star
49

abstractapi-rs

Rust API bindings for the Abstract HTTP API
Rust
1
star
50

rust-tui-example

A very simple TUI program to demonstrate on Rust Munich Meetup #8
Rust
1
star
51

ytpls

[experimental] YouTube Playlist Synchronizer backed by yt-dl & git
Rust
1
star