diff --git a/.config/bspwm/bspwmrc b/.config/bspwm/bspwmrc
index 2e89c2e..9384b31 100755
--- a/.config/bspwm/bspwmrc
+++ b/.config/bspwm/bspwmrc
@@ -17,8 +17,10 @@ bspc rule -a Nvidia-settings state=floating
bspc rule -a openrgb state=floating
bspc rule -a Sxiv state=floating
-dunst &
+pgrep -x dunst > /dev/null || dunst &
-~/.config/bspwm/scripts/notify.sh &
+pgrep -x notify.sh > /dev/null || ~/.config/bspwm/scripts/notify.sh &
-picom &
+~/.config/bspwm/scripts/launch-polybar.sh &
+
+pgrep -x picom > /dev/null || picom &
diff --git a/.config/bspwm/scripts/launch-polybar.sh b/.config/bspwm/scripts/launch-polybar.sh
new file mode 100755
index 0000000..fffe598
--- /dev/null
+++ b/.config/bspwm/scripts/launch-polybar.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+killall -q polybar
+
+polybar primary 2>&1 | tee -a /tmp/polybar.log & disown
+polybar secondary 2>&1 | tee -a /tmp/polybar.log & disown
diff --git a/.config/bspwm/scripts/notify.sh b/.config/bspwm/scripts/notify.sh
index 666148b..8ad948b 100755
--- a/.config/bspwm/scripts/notify.sh
+++ b/.config/bspwm/scripts/notify.sh
@@ -10,12 +10,12 @@ while true; do
continue
fi
- current_track=$(playerctl -p Feishin metadata --format '{{ title }}\n{{ artist }}\n{{ album }}')
+ current_track=$(playerctl -p Feishin metadata --format '{{ title }} \n{{ artist }}\n{{ album }}')
album_art_url=$(playerctl -p Feishin metadata mpris:artUrl)
album_art_file="/tmp/album_art.jpg"
wget -q -O $album_art_file $album_art_url
if [[ "$current_track" != "$previous_track" ]]; then
- notify-send "Now Playing" "$current_track" -i $album_art_file
+ notify-send "now playing" "$current_track" -i $album_art_file
previous_track="$current_track"
fi
sleep 1
diff --git a/.config/cava/config b/.config/cava/config
new file mode 100644
index 0000000..d8d2c13
--- /dev/null
+++ b/.config/cava/config
@@ -0,0 +1,271 @@
+## Configuration file for CAVA.
+# Remove the ; to change parameters.
+
+
+[general]
+
+# Smoothing mode. Can be 'normal', 'scientific' or 'waves'. DEPRECATED as of 0.6.0
+; mode = normal
+
+# Accepts only non-negative values.
+; framerate = 30
+
+# 'autosens' will attempt to decrease sensitivity if the bars peak. 1 = on, 0 = off
+# new as of 0.6.0 autosens of low values (dynamic range)
+# 'overshoot' allows bars to overshoot (in % of terminal height) without initiating autosens. DEPRECATED as of 0.6.0
+; autosens = 1
+; overshoot = 20
+
+# Manual sensitivity in %. If autosens is enabled, this will only be the initial value.
+# 200 means double height. Accepts only non-negative values.
+; sensitivity = 100
+
+# The number of bars (0-512). 0 sets it to auto (fill up console).
+# Bars' width and space between bars in number of characters.
+; bars = 0
+; bar_width = 2
+; bar_spacing = 1
+# bar_height is only used for output in "noritake" format
+; bar_height = 32
+
+# For SDL width and space between bars is in pixels, defaults are:
+; bar_width = 20
+; bar_spacing = 5
+
+# sdl_glsl have these default values, they are only used to calulate max number of bars.
+; bar_width = 1
+; bar_spacing = 0
+
+
+# Lower and higher cutoff frequencies for lowest and highest bars
+# the bandwidth of the visualizer.
+# Note: there is a minimum total bandwidth of 43Mhz x number of bars.
+# Cava will automatically increase the higher cutoff if a too low band is specified.
+; lower_cutoff_freq = 50
+; higher_cutoff_freq = 10000
+
+
+# Seconds with no input before cava goes to sleep mode. Cava will not perform FFT or drawing and
+# only check for input once per second. Cava will wake up once input is detected. 0 = disable.
+; sleep_timer = 0
+
+
+[input]
+
+# Audio capturing method. Possible methods are: 'fifo', 'portaudio', 'pipewire', 'alsa', 'pulse', 'sndio', 'oss' or 'shmem'
+# Defaults to 'oss', 'sndio', 'pipewire', 'pulse', 'alsa', 'portaudio' or 'fifo', in that order, dependent on what support cava was built with.
+# On Mac it defaults to 'portaudio' or 'fifo'
+# On windows this is automatic and no input settings are needed.
+#
+# All input methods uses the same config variable 'source'
+# to define where it should get the audio.
+#
+# For pulseaudio and pipewire 'source' will be the source. Default: 'auto', which uses the monitor source of the default sink
+# (all pulseaudio sinks(outputs) have 'monitor' sources(inputs) associated with them).
+#
+# For pipewire 'source' will be the object name or object.serial of the device to capture from.
+# Both input and output devices are supported.
+#
+# For alsa 'source' will be the capture device.
+# For fifo 'source' will be the path to fifo-file.
+# For shmem 'source' will be /squeezelite-AA:BB:CC:DD:EE:FF where 'AA:BB:CC:DD:EE:FF' will be squeezelite's MAC address
+#
+# For sndio 'source' will be a monitor sub-device, e.g. 'snd/0.monitor'. Default: 'default', in which case a device
+# should be specified with the environment variable AUDIODEVICE, e.g. on the commandline: AUDIODEVICE=snd/0.monitor cava.
+#
+# For oss 'source' will be the path to a audio device, e.g. '/dev/dsp2'. Default: '/dev/dsp', i.e. the default audio device.
+# README.md contains further information on how to setup CAVA for OSS on FreeBSD.
+#
+; method = pulse
+; source = auto
+
+method = pipewire
+source = auto
+
+; method = alsa
+; source = hw:Loopback,1
+
+; method = fifo
+; source = /tmp/mpd.fifo
+
+; method = shmem
+; source = /squeezelite-AA:BB:CC:DD:EE:FF
+
+; method = portaudio
+; source = auto
+
+; method = sndio
+; source = default
+
+; method = oss
+; source = /dev/dsp
+
+# The sample rate and format can be configured for some input methods. Currently
+# the following methods support such a configuration: 'fifo', 'pipewire' and 'oss'.
+# Other methods ignore these settings.
+#
+# For 'oss' they are only preferred values, i.e. if the values are not supported
+# by the chosen audio device, the device will use other supported values instead.
+# Example: 48000 and 32, but the device only supports 44100 and 16, then it will
+# use 44100 and 16.
+#
+; sample_rate = 44100
+; sample_bits = 16
+
+
+[output]
+
+# Output method. Can be 'ncurses', 'noncurses', 'raw', 'noritake', 'sdl'
+# or 'sdl_glsl'.
+# 'noncurses' (default) uses a buffer and cursor movements to only print
+# changes from frame to frame in the terminal. Uses less resources and is less
+# prone to tearing (vsync issues) than 'ncurses'.
+#
+# 'raw' is an 8 or 16 bit (configurable via the 'bit_format' option) data
+# stream of the bar heights that can be used to send to other applications.
+# 'raw' defaults to 200 bars, which can be adjusted in the 'bars' option above.
+#
+# 'noritake' outputs a bitmap in the format expected by a Noritake VFD display
+# in graphic mode. It only support the 3000 series graphical VFDs for now.
+#
+# 'sdl' uses the Simple DirectMedia Layer to render in a graphical context.
+# 'sdl_glsl' uses SDL to create an OpenGL context. Write your own shaders or
+# use one of the predefined ones.
+; method = noncurses
+
+# Orientation of the visualization. Can be 'bottom', 'top', 'left' or 'right'.
+# Default is 'bottom'. Other orientations are only supported on sdl and ncruses
+# output. Note: many fonts have weird glyphs for 'top' and 'right' characters,
+# which can make ncurses not look right.
+; orientation = bottom
+
+# Visual channels. Can be 'stereo' or 'mono'.
+# 'stereo' mirrors both channels with low frequencies in center.
+# 'mono' outputs left to right lowest to highest frequencies.
+# 'mono_option' set mono to either take input from 'left', 'right' or 'average'.
+# set 'reverse' to 1 to display frequencies the other way around.
+channels = mono
+mono_option = average
+; reverse = 0
+
+# Raw output target. A fifo will be created if target does not exist.
+; raw_target = /dev/stdout
+
+# Raw data format. Can be 'binary' or 'ascii'.
+; data_format = binary
+
+# Binary bit format, can be '8bit' (0-255) or '16bit' (0-65530).
+; bit_format = 16bit
+
+# Ascii max value. In 'ascii' mode range will run from 0 to value specified here
+; ascii_max_range = 1000
+
+# Ascii delimiters. In ascii format each bar and frame is separated by a delimiters.
+# Use decimal value in ascii table (i.e. 59 = ';' and 10 = '\n' (line feed)).
+; bar_delimiter = 59
+; frame_delimiter = 10
+
+# sdl window size and position. -1,-1 is centered.
+; sdl_width = 1000
+; sdl_height = 500
+; sdl_x = -1
+; sdl_y= -1
+; sdl_full_screen = 0
+
+# set label on bars on the x-axis. Can be 'frequency' or 'none'. Default: 'none'
+# 'frequency' displays the lower cut off frequency of the bar above.
+# Only supported on ncurses and noncurses output.
+; xaxis = none
+
+# enable alacritty synchronized updates. 1 = on, 0 = off
+# removes flickering in alacritty terminal emulator.
+# defaults to off since the behaviour in other terminal emulators is unknown
+; alacritty_sync = 0
+
+# Shaders for sdl_glsl, located in $HOME/.config/cava/shaders
+; vertex_shader = pass_through.vert
+; fragment_shader = bar_spectrum.frag
+
+; for glsl output mode, keep rendering even if no audio
+; continuous_rendering = 0
+
+# disable console blank (screen saver) in tty
+# (Not supported on FreeBSD)
+; disable_blanking = 0
+
+[color]
+
+# Colors can be one of seven predefined: black, blue, cyan, green, magenta, red, white, yellow.
+# Or defined by hex code '#xxxxxx' (hex code must be within ''). User defined colors requires
+# a terminal that can change color definitions such as Gnome-terminal or rxvt.
+# default is to keep current terminal color
+; background = default
+; foreground = default
+
+# SDL and sdl_glsl only support hex code colors, these are the default:
+; background = '#111111'
+; foreground = '#D3C6AA'
+
+
+# Gradient mode, only hex defined colors are supported,
+# background must also be defined in hex or remain commented out. 1 = on, 0 = off.
+# You can define as many as 8 different colors. They range from bottom to top of screen
+; gradient = 0
+; gradient_count = 8
+; gradient_color_1 = '#59cc33'
+; gradient_color_2 = '#80cc33'
+; gradient_color_3 = '#a6cc33'
+; gradient_color_4 = '#cccc33'
+; gradient_color_5 = '#cca633'
+; gradient_color_6 = '#cc8033'
+; gradient_color_7 = '#cc5933'
+; gradient_color_8 = '#cc3333'
+
+# everforest colors
+gradient = 1
+gradient_count = 5
+gradient_color_1 = '#A8C181'
+gradient_color_2 = '#BFB26D'
+gradient_color_3 = '#D3A165'
+gradient_color_4 = '#E18F6C'
+gradient_color_5 = '#E77E7F'
+
+
+
+[smoothing]
+
+# Percentage value for integral smoothing. Takes values from 0 - 100.
+# Higher values means smoother, but less precise. 0 to disable.
+# DEPRECATED as of 0.8.0, use noise_reduction instead
+; integral = 77
+
+# Disables or enables the so-called "Monstercat smoothing" with or without "waves". Set to 0 to disable.
+; monstercat = 0
+; waves = 0
+
+# Set gravity percentage for "drop off". Higher values means bars will drop faster.
+# Accepts only non-negative values. 50 means half gravity, 200 means double. Set to 0 to disable "drop off".
+# DEPRECATED as of 0.8.0, use noise_reduction instead
+; gravity = 100
+
+
+# In bar height, bars that would have been lower that this will not be drawn.
+# DEPRECATED as of 0.8.0
+; ignore = 0
+
+# Noise reduction, int 0 - 100. default 77
+# the raw visualization is very noisy, this factor adjusts the integral and gravity filters to keep the signal smooth
+# 100 will be very slow and smooth, 0 will be fast but noisy.
+noise_reduction = 40
+
+
+[eq]
+
+# This one is tricky. You can have as much keys as you want.
+# Remember to uncomment more than one key! More keys = more precision.
+# Look at readme.md on github for further explanations and examples.
+; 1 = 1 # bass
+; 2 = 1
+; 3 = 1 # midtone
+; 4 = 1
+; 5 = 1 # treble
diff --git a/.config/dunst/dunstrc b/.config/dunst/dunstrc
new file mode 100644
index 0000000..f8fc485
--- /dev/null
+++ b/.config/dunst/dunstrc
@@ -0,0 +1,462 @@
+# See dunst(5) for all configuration options
+
+[global]
+ ### Display ###
+
+ # Which monitor should the notifications be displayed on.
+ monitor = 0
+
+ # Display notification on focused monitor. Possible modes are:
+ # mouse: follow mouse pointer
+ # keyboard: follow window with keyboard focus
+ # none: don't follow anything
+ #
+ # "keyboard" needs a window manager that exports the
+ # _NET_ACTIVE_WINDOW property.
+ # This should be the case for almost all modern window managers.
+ #
+ # If this option is set to mouse or keyboard, the monitor option
+ # will be ignored.
+ # follow = keyboard
+
+ ### Geometry ###
+
+ # dynamic width from 0 to 300
+ # width = (0, 300)
+ # constant width of 300
+ width = (200, 600)
+
+ # The maximum height of a single notification, excluding the frame.
+ height = 300
+
+ # Position the notification in the top right corner
+ origin = top-right
+
+ # Offset from the origin
+ offset = 10x36
+
+ # Scale factor. It is auto-detected if value is 0.
+ scale = 1
+
+ # Maximum number of notification (0 means no limit)
+ notification_limit = 10
+
+ ### Progress bar ###
+
+ # Turn on the progess bar. It appears when a progress hint is passed with
+ # for example dunstify -h int:value:12
+ progress_bar = true
+
+ # Set the progress bar height. This includes the frame, so make sure
+ # it's at least twice as big as the frame width.
+ progress_bar_height = 10
+
+ # Set the frame width of the progress bar
+ progress_bar_frame_width = 1
+
+ # Set the minimum width for the progress bar
+ progress_bar_min_width = 150
+
+ # Set the maximum width for the progress bar
+ progress_bar_max_width = 300
+
+ # Corner radius for the progress bar. 0 disables rounded corners.
+ progress_bar_corner_radius = 0
+
+ # Corner radius for the icon image.
+ icon_corner_radius = 0
+
+ # Show how many messages are currently hidden (because of
+ # notification_limit).
+ indicate_hidden = yes
+
+ # The transparency of the window. Range: [0; 100].
+ # This option will only work if a compositing window manager is
+ # present (e.g. xcompmgr, compiz, etc.). (X11 only)
+ transparency = 5
+
+ # Draw a line of "separator_height" pixel height between two
+ # notifications.
+ # Set to 0 to disable.
+ # If gap_size is greater than 0, this setting will be ignored.
+ separator_height = 2
+
+ # Padding between text and separator.
+ padding = 15
+
+ # Horizontal padding.
+ horizontal_padding = 15
+
+ # Padding between text and icon.
+ text_icon_padding = 0
+
+ # Defines width in pixels of frame around the notification window.
+ # Set to 0 to disable.
+ frame_width = 3
+
+ # Defines color of the frame around the notification window.
+ frame_color = "#7A8478"
+
+ # Size of gap to display between notifications - requires a compositor.
+ # If value is greater than 0, separator_height will be ignored and a border
+ # of size frame_width will be drawn around each notification instead.
+ # Click events on gaps do not currently propagate to applications below.
+ gap_size = 0
+
+ # Define a color for the separator.
+ # possible values are:
+ # * auto: dunst tries to find a color fitting to the background;
+ # * foreground: use the same color as the foreground;
+ # * frame: use the same color as the frame;
+ # * anything else will be interpreted as a X color.
+ separator_color = frame
+
+ # Sort messages by urgency.
+ sort = yes
+
+ # Don't remove messages, if the user is idle (no mouse or keyboard input)
+ # for longer than idle_threshold seconds.
+ # Set to 0 to disable.
+ # A client can set the 'transient' hint to bypass this. See the rules
+ # section for how to disable this if necessary
+ # idle_threshold = 120
+
+ ### Text ###
+
+ font = JetBrainsMonoNL Nerd Font Mono 12
+
+ # The spacing between lines. If the height is smaller than the
+ # font height, it will get raised to the font height.
+ line_height = 2
+
+ # Possible values are:
+ # full: Allow a small subset of html markup in notifications:
+ # bold
+ # italic
+ # strikethrough
+ # underline
+ #
+ # For a complete reference see
+ # .
+ #
+ # strip: This setting is provided for compatibility with some broken
+ # clients that send markup even though it's not enabled on the
+ # server. Dunst will try to strip the markup but the parsing is
+ # simplistic so using this option outside of matching rules for
+ # specific applications *IS GREATLY DISCOURAGED*.
+ #
+ # no: Disable markup parsing, incoming notifications will be treated as
+ # plain text. Dunst will not advertise that it has the body-markup
+ # capability if this is set as a global setting.
+ #
+ # It's important to note that markup inside the format option will be parsed
+ # regardless of what this is set to.
+ markup = full
+
+ # The format of the message. Possible variables are:
+ # %a appname
+ # %s summary
+ # %b body
+ # %i iconname (including its path)
+ # %I iconname (without its path)
+ # %p progress value if set ([ 0%] to [100%]) or nothing
+ # %n progress value if set without any extra characters
+ # %% Literal %
+ # Markup is allowed
+ format = "%s \n%b\n"
+
+ # Alignment of message text.
+ # Possible values are "left", "center" and "right".
+ alignment = left
+
+ # Vertical alignment of message text and icon.
+ # Possible values are "top", "center" and "bottom".
+ vertical_alignment = top
+
+ # Show age of message if message is older than show_age_threshold
+ # seconds.
+ # Set to -1 to disable.
+ show_age_threshold = 60
+
+ # Specify where to make an ellipsis in long lines.
+ # Possible values are "start", "middle" and "end".
+ ellipsize = end
+
+ # Ignore newlines '\n' in notifications.
+ ignore_newline = no
+
+ # Stack together notifications with the same content
+ stack_duplicates = true
+
+ # Hide the count of stacked notifications with the same content
+ hide_duplicate_count = false
+
+ # Display indicators for URLs (U) and actions (A).
+ show_indicators = yes
+
+ ### Icons ###
+
+ # Recursive icon lookup. You can set a single theme, instead of having to
+ # define all lookup paths.
+ enable_recursive_icon_lookup = true
+
+ # Set icon theme (only used for recursive icon lookup)
+ icon_theme = Reversal-black-dark
+ # You can also set multiple icon themes, with the leftmost one being used first.
+ # icon_theme = "Adwaita, breeze"
+
+ # Align icons left/right/top/off
+ icon_position = left
+
+ # Scale small icons up to this size, set to 0 to disable. Helpful
+ # for e.g. small files or high-dpi screens. In case of conflict,
+ # max_icon_size takes precedence over this.
+ min_icon_size = 22
+
+ # Scale larger icons down to this size, set to 0 to disable
+ max_icon_size = 128
+
+ # Paths to default icons (only neccesary when not using recursive icon lookup)
+ #icon_path = /usr/share/icons/gnome/16x16/status/:/usr/share/icons/gnome/16x16/devices/
+ icon_path = ~/.local/share/icons/Reversal-black-dark/devices/16/
+
+ ### History ###
+
+ # Should a notification popped up from history be sticky or timeout
+ # as if it would normally do.
+ sticky_history = yes
+
+ # Maximum amount of notifications kept in history
+ history_length = 50
+
+ ### Misc/Advanced ###
+
+ # dmenu path.
+ dmenu = /usr/bin/rofi -dmenu -p " dunst "
+
+ # Browser for opening urls in context menu.
+ browser = /usr/bin/xdg-open
+
+ # Always run rule-defined scripts, even if the notification is suppressed
+ always_run_script = true
+
+ # Define the title of the windows spawned by dunst
+ title = dunst
+
+ # Define the class of the windows spawned by dunst
+ class = dunst
+
+ # Define the corner radius of the notification window
+ # in pixel size. If the radius is 0, you have no rounded
+ # corners.
+ # The radius will be automatically lowered if it exceeds half of the
+ # notification height to avoid clipping text and/or icons.
+ corner_radius = 0
+
+ # Ignore the dbus closeNotification message.
+ # Useful to enforce the timeout set by dunst configuration. Without this
+ # parameter, an application may close the notification sent before the
+ # user defined timeout.
+ ignore_dbusclose = false
+
+ ### Wayland ###
+ # These settings are Wayland-specific. They have no effect when using X11
+
+ # Uncomment this if you want to let notications appear under fullscreen
+ # applications (default: overlay)
+ # layer = top
+
+ # Set this to true to use X11 output on Wayland.
+ force_xwayland = false
+
+ ### Legacy
+
+ # Use the Xinerama extension instead of RandR for multi-monitor support.
+ # This setting is provided for compatibility with older nVidia drivers that
+ # do not support RandR and using it on systems that support RandR is highly
+ # discouraged.
+ #
+ # By enabling this setting dunst will not be able to detect when a monitor
+ # is connected or disconnected which might break follow mode if the screen
+ # layout changes.
+ force_xinerama = false
+
+ ### mouse
+
+ # Defines list of actions for each mouse event
+ # Possible values are:
+ # * none: Don't do anything.
+ # * do_action: Invoke the action determined by the action_name rule. If there is no
+ # such action, open the context menu.
+ # * open_url: If the notification has exactly one url, open it. If there are multiple
+ # ones, open the context menu.
+ # * close_current: Close current notification.
+ # * close_all: Close all notifications.
+ # * context: Open context menu for the notification.
+ # * context_all: Open context menu for all notifications.
+ # These values can be strung together for each mouse event, and
+ # will be executed in sequence.
+ mouse_left_click = do_action, close_current
+ mouse_middle_click = close_all
+ mouse_right_click = close_current
+
+# Experimental features that may or may not work correctly. Do not expect them
+# to have a consistent behaviour across releases.
+[experimental]
+ # Calculate the dpi to use on a per-monitor basis.
+ # If this setting is enabled the Xft.dpi value will be ignored and instead
+ # dunst will attempt to calculate an appropriate dpi value for each monitor
+ # using the resolution and physical size. This might be useful in setups
+ # where there are multiple screens with very different dpi values.
+ per_monitor_dpi = false
+
+
+[urgency_low]
+ # IMPORTANT: colors have to be defined in quotation marks.
+ # Otherwise the "#" and following would be interpreted as a comment.
+ background = "#232A2E"
+ foreground = "#D3C6AA" #gray2#
+ highlight = "#A7C080"
+ timeout = 10
+ # Icon for notifications with low urgency, uncomment to enable
+ #default_icon = /path/to/icon
+
+[urgency_normal]
+ background = "#232A2E"
+ foreground = "#D3C6AA" #bejsikFG#
+ highlight = "#A7C080"
+ timeout = 10
+ # Icon for notifications with normal urgency, uncomment to enable
+ #default_icon = /path/to/icon
+
+[urgency_critical]
+ background = "#232A2E"
+ foreground = "#E69875" #orange#
+ frame_color = "#E67E80" #red#
+ timeout = 0
+ # Icon for notifications with critical urgency, uncomment to enable
+ #default_icon = /path/to/icon
+
+# Every section that isn't one of the above is interpreted as a rules to
+# override settings for certain messages.
+#
+# Messages can be matched by
+# appname (discouraged, see desktop_entry)
+# body
+# category
+# desktop_entry
+# icon
+# match_transient
+# msg_urgency
+# stack_tag
+# summary
+#
+# and you can override the
+# background
+# foreground
+# format
+# frame_color
+# fullscreen
+# new_icon
+# set_stack_tag
+# set_transient
+# set_category
+# timeout
+# urgency
+# icon_position
+# skip_display
+# history_ignore
+# action_name
+# word_wrap
+# ellipsize
+# alignment
+# hide_text
+#
+# Shell-like globbing will get expanded.
+#
+# Instead of the appname filter, it's recommended to use the desktop_entry filter.
+# GLib based applications export their desktop-entry name. In comparison to the appname,
+# the desktop-entry won't get localized.
+#
+# SCRIPTING
+# You can specify a script that gets run when the rule matches by
+# setting the "script" option.
+# The script will be called as follows:
+# script appname summary body icon urgency
+# where urgency can be "LOW", "NORMAL" or "CRITICAL".
+#
+# NOTE: It might be helpful to run dunst -print in a terminal in order
+# to find fitting options for rules.
+
+# Disable the transient hint so that idle_threshold cannot be bypassed from the
+# client
+#[transient_disable]
+# match_transient = yes
+# set_transient = no
+#
+# Make the handling of transient notifications more strict by making them not
+# be placed in history.
+#[transient_history_ignore]
+# match_transient = yes
+# history_ignore = yes
+
+# fullscreen values
+# show: show the notifications, regardless if there is a fullscreen window opened
+# delay: displays the new notification, if there is no fullscreen window active
+# If the notification is already drawn, it won't get undrawn.
+# pushback: same as delay, but when switching into fullscreen, the notification will get
+# withdrawn from screen again and will get delayed like a new notification
+#[fullscreen_delay_everything]
+# fullscreen = delay
+#[fullscreen_show_critical]
+# msg_urgency = critical
+# fullscreen = show
+
+#[espeak]
+# summary = "*"
+# script = dunst_espeak.sh
+
+#[script-test]
+# summary = "*script*"
+# script = dunst_test.sh
+
+#[ignore]
+# # This notification will not be displayed
+# summary = "foobar"
+# skip_display = true
+
+#[history-ignore]
+# # This notification will not be saved in history
+# summary = "foobar"
+# history_ignore = yes
+
+#[skip-display]
+# # This notification will not be displayed, but will be included in the history
+# summary = "foobar"
+# skip_display = yes
+
+#[signed_on]
+# appname = Pidgin
+# summary = "*signed on*"
+# urgency = low
+#
+#[signed_off]
+# appname = Pidgin
+# summary = *signed off*
+# urgency = low
+#
+#[says]
+# appname = Pidgin
+# summary = *says*
+# urgency = critical
+#
+#[twitter]
+# appname = Pidgin
+# summary = *twitter.com*
+# urgency = normal
+#
+#[stack-volumes]
+# appname = "some_volume_notifiers"
+# set_stack_tag = "volume"
+#
+# vim: ft=cfg
diff --git a/.config/polybar/config.ini b/.config/polybar/config.ini
new file mode 100644
index 0000000..f5bccca
--- /dev/null
+++ b/.config/polybar/config.ini
@@ -0,0 +1,259 @@
+;==========================================================
+;
+;
+; ██████╗ ██████╗ ██╗ ██╗ ██╗██████╗ █████╗ ██████╗
+; ██╔══██╗██╔═══██╗██║ ╚██╗ ██╔╝██╔══██╗██╔══██╗██╔══██╗
+; ██████╔╝██║ ██║██║ ╚████╔╝ ██████╔╝███████║██████╔╝
+; ██╔═══╝ ██║ ██║██║ ╚██╔╝ ██╔══██╗██╔══██║██╔══██╗
+; ██║ ╚██████╔╝███████╗██║ ██████╔╝██║ ██║██║ ██║
+; ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝
+;
+;
+; To learn more about how to configure Polybar
+; go to https://github.com/polybar/polybar
+;
+; The README contains a lot of information
+;
+;==========================================================
+
+[colors]
+background = #000000
+background-alt = #373B41
+foreground = #C5C8C6
+primary = #A7C080
+secondary = #8ABEB7
+alert = #A54242
+disabled = #707880
+
+[bar/primary]
+width = 100%
+height = 24pt
+radius = 0
+
+monitor = DP-2
+
+; dpi = 96
+
+background = ${colors.background}
+foreground = ${colors.foreground}
+
+line-size = 3pt
+
+border-size = 0pt
+
+padding-left = 0
+padding-right = 1
+
+module-margin = 1
+separator = |
+separator-foreground = ${colors.disabled}
+
+font-0 = "JetBrainsMonoNL Nerd Font Mono:pixelsize=12;2"
+
+modules-left = bspwm xwindow
+modules-center = date
+modules-right = music filesystem memory cpu wlan
+
+cursor-click = pointer
+cursor-scroll = ns-resize
+
+enable-ipc = true
+
+; wm-restack = generic
+wm-restack = bspwm
+wm-name = bspwm
+; wm-restack = i3
+
+; override-redirect = true
+
+[bar/secondary]
+width = 100%
+height = 24pt
+radius = 0
+
+monitor = HDMI-0
+
+; dpi = 96
+
+background = ${colors.background}
+foreground = ${colors.foreground}
+
+line-size = 3pt
+
+border-size = 0pt
+
+padding-left = 0
+padding-right = 1
+
+module-margin = 1
+separator = |
+separator-foreground = ${colors.disabled}
+
+font-0 = "JetBrainsMonoNL Nerd Font Mono:pixelsize=12;2"
+
+modules-left = bspwm xwindow
+modules-center = date
+modules-right = music filesystem memory cpu wlan
+
+cursor-click = pointer
+cursor-scroll = ns-resize
+
+enable-ipc = true
+
+; wm-restack = generic
+wm-restack = bspwm
+wm-name = bspwm
+; wm-restack = i3
+
+; override-redirect = true
+
+[module/systray]
+type = internal/tray
+
+format-margin = 8pt
+tray-spacing = 16pt
+
+[module/bspwm]
+type = internal/bspwm
+pin-workspaces = true
+
+format =
+
+label-focused = " %name% "
+label-focused-foreground = ${colors.background}
+label-focused-background = ${colors.primary}
+
+label-occupied = " %name% "
+label-empty = " %name% "
+label-urgent = " %name% "
+
+label-dimmed = " %name% "
+label-dimmed-foreground = ${colors.foreground}
+label-dimmed-underline = ${bar/top.background}
+
+label-dimmed-focused = " %name% "
+label-dimmed-focused-background = ${colors.secondary}
+label-dimmed-focused-foreground = ${colors.background}
+
+[module/xworkspaces]
+type = internal/xworkspaces
+
+label-active = %name%
+label-active-background = ${colors.background-alt}
+label-active-underline= ${colors.primary}
+label-active-padding = 1
+
+label-occupied = %name%
+label-occupied-padding = 1
+
+label-urgent = %name%
+label-urgent-background = ${colors.alert}
+label-urgent-padding = 1
+
+label-empty = %name%
+label-empty-foreground = ${colors.disabled}
+label-empty-padding = 1
+
+[module/xwindow]
+type = internal/xwindow
+label = %title:0:60:...%
+
+[module/music]
+type = custom/script
+exec = ~/.config/polybar/scripts/player-mpris-tail/player-mpris-tail.py -f '%{F#A7C080}{icon}%{F-} {artist} - {title}' --icon-playing --icon-paused --icon-none --icon-stopped
+tail = true
+click-middle = ~/.config/polybar/scripts/player-mpris-tail/player-mpris-tail.py previous &
+click-right = ~/.config/polybar/scripts/player-mpris-tail/player-mpris-tail.py next &
+click-left = ~/.config/polybar/scripts/player-mpris-tail/player-mpris-tail.py play-pause &
+icon-playing =
+
+[module/filesystem]
+type = internal/fs
+interval = 25
+
+mount-0 = /
+
+label-mounted = %{F#A7C080}%mountpoint%%{F-} %percentage_used%%
+
+label-unmounted = %mountpoint% not mounted
+label-unmounted-foreground = ${colors.disabled}
+
+[module/redshift]
+type = custom/script
+format-prefix = " "
+exec = source ~/.config/polybar/scripts/polybar-redshift/env.sh && ~/.config/polybar/scripts/polybar-redshift/redshift.sh temperature
+click-left = source ~/.config/polybar/scripts/polybar-redshift/env.sh && ~/.config/polybar/polybar-redshift/scripts/redshift.sh toggle
+scroll-up = source ~/.config/polybar/scripts/polybar-redshift/env.sh && ~/.config/polybar/scripts/polybar-redshift/redshift.sh increase
+scroll-down = source ~/.config/polybar/scripts/polybar-redshift/env.sh && ~/.config/polybar/scripts/polybar-redshift/redshift.sh decrease
+interval=0.5
+
+[module/pulseaudio]
+type = internal/pulseaudio
+
+format-volume-prefix = "vol "
+format-volume-prefix-foreground = ${colors.primary}
+format-volume =
+
+label-volume = %percentage%%
+
+label-muted = muted
+label-muted-foreground = ${colors.disabled}
+
+[module/xkeyboard]
+type = internal/xkeyboard
+blacklist-0 = num lock
+
+label-layout = %layout%
+label-layout-foreground = ${colors.primary}
+
+label-indicator-padding = 2
+label-indicator-margin = 1
+label-indicator-foreground = ${colors.background}
+label-indicator-background = ${colors.secondary}
+
+[module/memory]
+type = internal/memory
+interval = 2
+format-prefix = "ram "
+format-prefix-foreground = ${colors.primary}
+label = %percentage_used:2%%
+
+[module/cpu]
+type = internal/cpu
+interval = 2
+format-prefix = "cpu "
+format-prefix-foreground = ${colors.primary}
+label = %percentage:2%%
+
+[network-base]
+type = internal/network
+interval = 5
+format-connected =
+format-disconnected =
+label-disconnected = %{F#A7C080}%ifname%%{F#707880} disconnected
+
+[module/wlan]
+inherit = network-base
+interface-type = wireless
+label-connected = %{F#A7C080}%ifname%%{F-} %essid% %local_ip%
+
+[module/eth]
+inherit = network-base
+interface-type = wired
+label-connected = %{F#A7C080}%ifname%%{F-} %local_ip%
+
+[module/date]
+type = internal/date
+interval = 1
+
+date = %A, %d %B %H:%M
+date-alt = %Y-%m-%d %H:%M:%S
+
+label = %date%
+label-foreground = ${colors.primary}
+
+[settings]
+screenchange-reload = true
+pseudo-transparency = true
+
+; vim:ft=dosini
diff --git a/.config/polybar/scripts/battery-combined-shell/README.md b/.config/polybar/scripts/battery-combined-shell/README.md
new file mode 100644
index 0000000..37800d6
--- /dev/null
+++ b/.config/polybar/scripts/battery-combined-shell/README.md
@@ -0,0 +1,15 @@
+# Script: battery-combined-shell
+
+A shell script that shows the battery status.
+
+It supports two rechargeable batteries and changing icons. It works even if only one battery is used.
+
+
+## Module
+
+```ini
+[module/battery-combined-shell]
+type = custom/script
+exec = ~/polybar-scripts/battery-combined-shell.sh
+interval = 10
+```
diff --git a/.config/polybar/scripts/battery-combined-shell/battery-combined-shell.sh b/.config/polybar/scripts/battery-combined-shell/battery-combined-shell.sh
new file mode 100644
index 0000000..9466ce2
--- /dev/null
+++ b/.config/polybar/scripts/battery-combined-shell/battery-combined-shell.sh
@@ -0,0 +1,61 @@
+#!/bin/sh
+
+PATH_AC="/sys/class/power_supply/AC"
+PATH_BATTERY_0="/sys/class/power_supply/BAT0"
+PATH_BATTERY_1="/sys/class/power_supply/BAT1"
+
+ac=0
+battery_level_0=0
+battery_level_1=0
+battery_max_0=0
+battery_max_1=0
+
+if [ -f "$PATH_AC/online" ]; then
+ ac=$(cat "$PATH_AC/online")
+fi
+
+if [ -f "$PATH_BATTERY_0/energy_now" ]; then
+ battery_level_0=$(cat "$PATH_BATTERY_0/energy_now")
+fi
+
+if [ -f "$PATH_BATTERY_0/energy_full" ]; then
+ battery_max_0=$(cat "$PATH_BATTERY_0/energy_full")
+fi
+
+if [ -f "$PATH_BATTERY_1/energy_now" ]; then
+ battery_level_1=$(cat "$PATH_BATTERY_1/energy_now")
+fi
+
+if [ -f "$PATH_BATTERY_1/energy_full" ]; then
+ battery_max_1=$(cat "$PATH_BATTERY_1/energy_full")
+fi
+
+battery_level=$(("$battery_level_0 + $battery_level_1"))
+battery_max=$(("$battery_max_0 + $battery_max_1"))
+
+battery_percent=$(("$battery_level * 100"))
+battery_percent=$(("$battery_percent / $battery_max"))
+
+if [ "$ac" -eq 1 ]; then
+ icon="#1"
+
+ if [ "$battery_percent" -gt 97 ]; then
+ echo "$icon"
+ else
+ echo "$icon $battery_percent %"
+ fi
+else
+ if [ "$battery_percent" -gt 85 ]; then
+ icon="#21"
+ elif [ "$battery_percent" -gt 60 ]; then
+ icon="#22"
+ elif [ "$battery_percent" -gt 35 ]; then
+ icon="#23"
+ elif [ "$battery_percent" -gt 10 ]; then
+ icon="#24"
+ else
+ icon="#25"
+ fi
+
+ echo "$icon $battery_percent %"
+fi
diff --git a/.config/polybar/scripts/battery-combined-tlp/README.md b/.config/polybar/scripts/battery-combined-tlp/README.md
new file mode 100644
index 0000000..0a11598
--- /dev/null
+++ b/.config/polybar/scripts/battery-combined-tlp/README.md
@@ -0,0 +1,31 @@
+# Script: battery-combined-tlp
+
+A shell script that shows the battery status.
+
+It uses TLP and requires root privileges. Note that the icon doesn't change.
+
+
+
+
+## Dependencies
+
+* `tlp`
+
+
+## Configuration
+
+You have to add the `tlp-stat` command to the `/etc/sudoers` NOPASSWD of your user:
+
+```ini
+user ALL=(ALL) NOPASSWD: /usr/bin/tlp-stat
+```
+
+
+## Module
+
+```ini
+[module/battery-combined-tlp]
+type = custom/script
+exec = ~/polybar-scripts/battery-combined-tlp.sh
+interval = 10
+```
diff --git a/.config/polybar/scripts/battery-combined-tlp/battery-combined-tlp.sh b/.config/polybar/scripts/battery-combined-tlp/battery-combined-tlp.sh
new file mode 100644
index 0000000..2e18b11
--- /dev/null
+++ b/.config/polybar/scripts/battery-combined-tlp/battery-combined-tlp.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+battery=$(sudo tlp-stat -b | tac | grep -m 1 "Charge" | tr -d -c "[:digit:],.")
+
+echo "# $battery %"
diff --git a/.config/polybar/scripts/battery-combined-tlp/screenshots/1.png b/.config/polybar/scripts/battery-combined-tlp/screenshots/1.png
new file mode 100644
index 0000000..7474a29
Binary files /dev/null and b/.config/polybar/scripts/battery-combined-tlp/screenshots/1.png differ
diff --git a/.config/polybar/scripts/battery-combined-udev/95-battery.rules b/.config/polybar/scripts/battery-combined-udev/95-battery.rules
new file mode 100644
index 0000000..d5d31b0
--- /dev/null
+++ b/.config/polybar/scripts/battery-combined-udev/95-battery.rules
@@ -0,0 +1,4 @@
+SUBSYSTEM=="power_supply", ENV{POWER_SUPPLY_ONLINE}=="0", \
+ RUN+="/home/user/.config/polybar/battery-combined-udev.sh --update"
+SUBSYSTEM=="power_supply", ENV{POWER_SUPPLY_ONLINE}=="1", \
+ RUN+="/home/user/.config/polybar/battery-combined-udev.sh --update"
diff --git a/.config/polybar/scripts/battery-combined-udev/README.md b/.config/polybar/scripts/battery-combined-udev/README.md
new file mode 100644
index 0000000..0fbc0ec
--- /dev/null
+++ b/.config/polybar/scripts/battery-combined-udev/README.md
@@ -0,0 +1,22 @@
+# Script: battery-combined-udev
+
+A shell script that shows the battery status. This is an extended version of [battery-combined-shell](../battery-combined-shell).
+
+It supports two rechargeable batteries and changing icons. It works even if only one battery is used.
+
+This script is able to display power supply changes in real time. For this udev is being used.
+
+
+## Configuration
+
+Copy `95-battery.rules` to `/etc/udev/rules.d/95-battery.rules`. Make sure that the paths in the file have been modified properly.
+
+
+## Module
+
+```ini
+[module/battery-combined-udev]
+type = custom/script
+exec = ~/polybar-scripts/battery-combined-udev.sh
+tail = true
+```
diff --git a/.config/polybar/scripts/battery-combined-udev/battery-combined-udev.sh b/.config/polybar/scripts/battery-combined-udev/battery-combined-udev.sh
new file mode 100644
index 0000000..2ad7a7c
--- /dev/null
+++ b/.config/polybar/scripts/battery-combined-udev/battery-combined-udev.sh
@@ -0,0 +1,88 @@
+#!/bin/sh
+
+battery_print() {
+ PATH_AC="/sys/class/power_supply/AC"
+ PATH_BATTERY_0="/sys/class/power_supply/BAT0"
+ PATH_BATTERY_1="/sys/class/power_supply/BAT1"
+
+ ac=0
+ battery_level_0=0
+ battery_level_1=0
+ battery_max_0=0
+ battery_max_1=0
+
+ if [ -f "$PATH_AC/online" ]; then
+ ac=$(cat "$PATH_AC/online")
+ fi
+
+ if [ -f "$PATH_BATTERY_0/energy_now" ]; then
+ battery_level_0=$(cat "$PATH_BATTERY_0/energy_now")
+ fi
+
+ if [ -f "$PATH_BATTERY_0/energy_full" ]; then
+ battery_max_0=$(cat "$PATH_BATTERY_0/energy_full")
+ fi
+
+ if [ -f "$PATH_BATTERY_1/energy_now" ]; then
+ battery_level_1=$(cat "$PATH_BATTERY_1/energy_now")
+ fi
+
+ if [ -f "$PATH_BATTERY_1/energy_full" ]; then
+ battery_max_1=$(cat "$PATH_BATTERY_1/energy_full")
+ fi
+
+ battery_level=$(("$battery_level_0 + $battery_level_1"))
+ battery_max=$(("$battery_max_0 + $battery_max_1"))
+
+ battery_percent=$(("$battery_level * 100"))
+ battery_percent=$(("$battery_percent / $battery_max"))
+
+ if [ "$ac" -eq 1 ]; then
+ icon="#1"
+
+ if [ "$battery_percent" -gt 97 ]; then
+ echo "$icon"
+ else
+ echo "$icon $battery_percent %"
+ fi
+ else
+ if [ "$battery_percent" -gt 85 ]; then
+ icon="#21"
+ elif [ "$battery_percent" -gt 60 ]; then
+ icon="#22"
+ elif [ "$battery_percent" -gt 35 ]; then
+ icon="#23"
+ elif [ "$battery_percent" -gt 10 ]; then
+ icon="#24"
+ else
+ icon="#25"
+ fi
+
+ echo "$icon $battery_percent %"
+ fi
+}
+
+path_pid="/tmp/polybar-battery-combined-udev.pid"
+
+case "$1" in
+ --update)
+ pid=$(cat $path_pid)
+
+ if [ "$pid" != "" ]; then
+ kill -10 "$pid"
+ fi
+ ;;
+ *)
+ echo $$ > $path_pid
+
+ trap exit INT
+ trap "echo" USR1
+
+ while true; do
+ battery_print
+
+ sleep 30 &
+ wait
+ done
+ ;;
+esac
diff --git a/.config/polybar/scripts/battery-cyberpower/README.md b/.config/polybar/scripts/battery-cyberpower/README.md
new file mode 100644
index 0000000..d02b2e7
--- /dev/null
+++ b/.config/polybar/scripts/battery-cyberpower/README.md
@@ -0,0 +1,29 @@
+# Script: battery-cyberpower
+
+A shell script that shows the battery status for CyberPower UPS devices.
+
+This script is able to display power supply changes in real time.
+
+
+## Dependencies
+
+* `pwrstat` from CyberPower's website
+
+
+## Configuration
+
+You have to add the `pwrstat` command to the `/etc/sudoers` NOPASSWD of your user:
+
+```ini
+user ALL=(ALL) NOPASSWD: /usr/bin/pwrstat
+```
+
+
+## Module
+
+```ini
+[module/battery-cyberpower]
+type = custom/script
+exec = ~/polybar-scripts/battery-cyberpower.sh
+tail = true
+```
diff --git a/.config/polybar/scripts/battery-cyberpower/battery-cyberpower.sh b/.config/polybar/scripts/battery-cyberpower/battery-cyberpower.sh
new file mode 100644
index 0000000..e3ba575
--- /dev/null
+++ b/.config/polybar/scripts/battery-cyberpower/battery-cyberpower.sh
@@ -0,0 +1,56 @@
+#!/bin/sh
+
+ICON_AC="#1"
+ICON_BATTERY_FULL="#21"
+ICON_BATTERY_GOOD="#22"
+ICON_BATTERY_LOW="#23"
+ICON_BATTERY_CAUTION="#24"
+ICON_BATTERY_EMPTY="#25"
+
+SHOW_ESTIMATION=1
+
+battery_print() {
+ battery_info="$(sudo pwrstat -status)"
+ battery_capacity="$(echo "$battery_info" | awk '/Capacity/{print $3}')"
+ battery_ac="$(echo "$battery_info" | awk '/Power Supply by/{print $4,$5}')"
+ battery_load="$(echo "$battery_info" | grep "Load" | cut -d \( -f 2 | tr -d ' %)')"
+ battery_remaining="$(echo "$battery_info" | awk '/Remaining Runtime/{print $3}')"
+
+ output=""
+
+ if [ "$battery_ac" = "Utility Power" ]; then
+ if [ "$battery_capacity" -gt 97 ]; then
+ output="$ICON_AC"
+ else
+ output="$ICON_AC $battery_capacity %"
+ fi
+ else
+ if [ "$battery_capacity" -gt 85 ]; then
+ output="$ICON_BATTERY_FULL $battery_capacity %"
+ elif [ "$battery_capacity" -gt 60 ]; then
+ output="$ICON_BATTERY_GOOD $battery_capacity %"
+ elif [ "$battery_capacity" -gt 35 ]; then
+ output="$ICON_BATTERY_LOW $battery_capacity %"
+ elif [ "$battery_capacity" -gt 10 ]; then
+ output="$ICON_BATTERY_CAUTION $battery_capacity %"
+ else
+ output="$ICON_BATTERY_EMPTY $battery_capacity %"
+ fi
+ fi
+
+ if [ "$SHOW_ESTIMATION" -eq 1 ]; then
+ output="$output ($battery_load % / $battery_remaining min)"
+ fi
+
+ echo "$output"
+}
+
+trap exit INT
+trap "echo" USR1
+
+while true; do
+ battery_print "$@"
+
+ sleep 30 &
+ wait
+done
diff --git a/.config/polybar/scripts/dunst-snooze/README.md b/.config/polybar/scripts/dunst-snooze/README.md
new file mode 100644
index 0000000..e2cc6bb
--- /dev/null
+++ b/.config/polybar/scripts/dunst-snooze/README.md
@@ -0,0 +1,16 @@
+# Script: dunst-snooze
+
+A script to disable/enable Dunst notifications. When disabled, notifications will still be created and saved by dunst until you enable it again.
+
+
+
+
+
+## Module
+```ini
+[module/dunst-snooze]
+type = custom/script
+exec = ~/polybar-scripts/dunst-snooze.sh
+interval = 10
+click-left = ~/polybar-scripts/dunst-snooze.sh --toggle &
+```
diff --git a/.config/polybar/scripts/dunst-snooze/dunst-snooze.sh b/.config/polybar/scripts/dunst-snooze/dunst-snooze.sh
new file mode 100644
index 0000000..547eb87
--- /dev/null
+++ b/.config/polybar/scripts/dunst-snooze/dunst-snooze.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+case "$1" in
+ --toggle)
+ dunstctl set-paused toggle
+ ;;
+ *)
+ if [ "$(dunstctl is-paused)" = "true" ]; then
+ echo "#1"
+ else
+ echo "#2"
+ fi
+ ;;
+esac
diff --git a/.config/polybar/scripts/dunst-snooze/screenshots/1.png b/.config/polybar/scripts/dunst-snooze/screenshots/1.png
new file mode 100644
index 0000000..f776e9f
Binary files /dev/null and b/.config/polybar/scripts/dunst-snooze/screenshots/1.png differ
diff --git a/.config/polybar/scripts/dunst-snooze/screenshots/2.png b/.config/polybar/scripts/dunst-snooze/screenshots/2.png
new file mode 100644
index 0000000..995d25a
Binary files /dev/null and b/.config/polybar/scripts/dunst-snooze/screenshots/2.png differ
diff --git a/.config/polybar/scripts/easteregg-pornhub/README.md b/.config/polybar/scripts/easteregg-pornhub/README.md
new file mode 100644
index 0000000..05c0776
--- /dev/null
+++ b/.config/polybar/scripts/easteregg-pornhub/README.md
@@ -0,0 +1,44 @@
+# Script: easteregg-pornhub
+
+A script that shows a button and opens a random video at a large porn website.
+
+
+
+
+## Configuration
+
+Set your browser at the `click-left` option in your module.
+
+You should also enable the overline and underline option in your polybar.
+
+```ini
+[bar/barname]
+
+overline-size = 5
+underline-size = 4
+```
+
+
+## Module
+
+```ini
+[module/easteregg-pornhub]
+type = custom/script
+exec = echo " hub "
+interval = 3600
+click-left = "firefox --private-window https://pornhub.com/random" &
+
+format =
+format-prefix = " Porn "
+format-prefix-foreground = #ffffff
+format-prefix-background = #000000
+
+format-overline = #000000
+format-underline = #000000
+format-foreground = #000000
+format-background = #ffa500
+
+format-suffix = " "
+format-suffix-background = #000000
+format-suffix-foreground = #000000
+```
diff --git a/.config/polybar/scripts/easteregg-pornhub/screenshots/1.png b/.config/polybar/scripts/easteregg-pornhub/screenshots/1.png
new file mode 100644
index 0000000..49f18a1
Binary files /dev/null and b/.config/polybar/scripts/easteregg-pornhub/screenshots/1.png differ
diff --git a/.config/polybar/scripts/inbox-imap-pythongpg/README.md b/.config/polybar/scripts/inbox-imap-pythongpg/README.md
new file mode 100644
index 0000000..d7e30b3
--- /dev/null
+++ b/.config/polybar/scripts/inbox-imap-pythongpg/README.md
@@ -0,0 +1,29 @@
+# Script: inbox-imap-pythongpg
+
+A script that shows if there are unread mails in your IMAPs inbox. Passwords are encrypted with gpg.
+
+
+
+
+## Configuration
+
+You must have a gpg key to secure your password in configuration files. Encrypt your password using your gpg key like this.
+
+```ini
+echo 'your password' > /tmp/imappass
+gpg -er 'your gpg keyid' /tmp/imappass
+mv /tmp/imappass.gpg ~/.imappass.gpg
+shred /tmp/imappass && rm /tmp/imappass
+```
+
+For Gmail, you must allow [less secure apps](https://myaccount.google.com/security#connectedapps).
+
+
+## Module
+
+```ini
+[module/inbox-imap-pythongpg]
+type = custom/script
+exec = ~/polybar-scripts/inbox-imap-pythongpg.py
+interval = 60
+```
diff --git a/.config/polybar/scripts/inbox-imap-pythongpg/inbox-imap-python.py b/.config/polybar/scripts/inbox-imap-pythongpg/inbox-imap-python.py
new file mode 100644
index 0000000..599a895
--- /dev/null
+++ b/.config/polybar/scripts/inbox-imap-pythongpg/inbox-imap-python.py
@@ -0,0 +1,14 @@
+#!/usr/bin/python
+
+import imaplib
+import os
+import subprocess
+
+completed_process = subprocess.run(['gpg', '-dq', os.path.join(os.getenv('HOME'), '.imappass.gpg')], check=True, stdout=subprocess.PIPE, encoding="utf-8");
+password = completed_process.stdout[:-1]
+obj = imaplib.IMAP4_SSL('imap.mail.net', 993)
+# Only put your email address below.
+obj.login('your email address', password)
+obj.select()
+
+print(len(obj.search(None, 'unseen')[1][0].split()))
diff --git a/.config/polybar/scripts/inbox-imap-pythongpg/screenshots/1.png b/.config/polybar/scripts/inbox-imap-pythongpg/screenshots/1.png
new file mode 100644
index 0000000..4e16b7c
Binary files /dev/null and b/.config/polybar/scripts/inbox-imap-pythongpg/screenshots/1.png differ
diff --git a/.config/polybar/scripts/inbox-imap-shellnetrc/.netrc b/.config/polybar/scripts/inbox-imap-shellnetrc/.netrc
new file mode 100644
index 0000000..af41d46
--- /dev/null
+++ b/.config/polybar/scripts/inbox-imap-shellnetrc/.netrc
@@ -0,0 +1,3 @@
+machine mail.server.tld
+ login username
+ password supersecretpw
diff --git a/.config/polybar/scripts/inbox-imap-shellnetrc/README.md b/.config/polybar/scripts/inbox-imap-shellnetrc/README.md
new file mode 100644
index 0000000..770ecd8
--- /dev/null
+++ b/.config/polybar/scripts/inbox-imap-shellnetrc/README.md
@@ -0,0 +1,27 @@
+# Script: inbox-imap-shellnetrc
+
+A script that shows if there are unread mails in your IMAP inbox.
+
+This script actually use IMAPs. `curl` can also handle unencrypted IMAP. You only need to change the protocol in the command.
+
+The login data is stored in a `.netrc`. This is more secure because the password is not visible in the process list.
+
+
+## Dependencies
+
+* `curl`
+
+
+## Configuration
+
+For Gmail, you must allow [less secure apps](https://myaccount.google.com/security#connectedapps).
+
+
+## Module
+
+```ini
+[module/inbox-imap-shellnetrc]
+type = custom/script
+exec = ~/polybar-scripts/inbox-imap-shellnetrc.sh
+interval = 60
+```
diff --git a/.config/polybar/scripts/inbox-imap-shellnetrc/inbox-imap-shellnetrc.sh b/.config/polybar/scripts/inbox-imap-shellnetrc/inbox-imap-shellnetrc.sh
new file mode 100644
index 0000000..fc68db8
--- /dev/null
+++ b/.config/polybar/scripts/inbox-imap-shellnetrc/inbox-imap-shellnetrc.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+SERVER=""
+NETRC=".netrc"
+
+inbox=$(curl -sf --netrc-file "$NETRC" -X "STATUS INBOX (UNSEEN)" imaps://"$SERVER"/INBOX | tr -d -c "[:digit:]")
+
+if [ "$inbox" ] && [ "$inbox" -gt 0 ]; then
+ echo "# $inbox"
+else
+ echo ""
+fi
diff --git a/.config/polybar/scripts/inbox-imap-shellpass/README.md b/.config/polybar/scripts/inbox-imap-shellpass/README.md
new file mode 100644
index 0000000..4ee06da
--- /dev/null
+++ b/.config/polybar/scripts/inbox-imap-shellpass/README.md
@@ -0,0 +1,22 @@
+# Script: inbox-imap-shellpass
+
+A script that shows if there are unread mails in your IMAP inbox.
+
+This script actually use IMAPs. `curl` can also handle unencrypted IMAP. You only need to change the protocol in the command.
+
+The login data can be stored in your `pass` password manager.
+
+
+## Dependencies
+
+* `curl`
+
+
+## Module
+
+```ini
+[module/inbox-imap-shellpass]
+type = custom/script
+exec = ~/polybar-scripts/inbox-imap-shellpass.sh
+interval = 60
+```
diff --git a/.config/polybar/scripts/inbox-imap-shellpass/inbox-imap-shellpass.sh b/.config/polybar/scripts/inbox-imap-shellpass/inbox-imap-shellpass.sh
new file mode 100644
index 0000000..09543cb
--- /dev/null
+++ b/.config/polybar/scripts/inbox-imap-shellpass/inbox-imap-shellpass.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+SERVER=""
+LOGIN=""
+PASS=""
+KEYGRIP=""
+
+if [ "$(gpg-connect-agent 'keyinfo --list' /bye | grep "$KEYGRIP" | awk '{ print $7 }')" = 1 ]; then
+ password=$(pass show "$PASS" | head -n 1)
+ inbox=$(echo "user = \"$LOGIN:$password\"" | curl -sf -K- -X "STATUS INBOX (UNSEEN)" imaps://"$SERVER"/INBOX | tr -d -c "[:digit:]")
+
+ if [ "$inbox" ] && [ "$inbox" -gt 0 ]; then
+ echo "# $inbox"
+ else
+ echo ""
+ fi
+else
+ echo ""
+fi
diff --git a/.config/polybar/scripts/inbox-pop3-shellnetrc/.netrc b/.config/polybar/scripts/inbox-pop3-shellnetrc/.netrc
new file mode 100644
index 0000000..af41d46
--- /dev/null
+++ b/.config/polybar/scripts/inbox-pop3-shellnetrc/.netrc
@@ -0,0 +1,3 @@
+machine mail.server.tld
+ login username
+ password supersecretpw
diff --git a/.config/polybar/scripts/inbox-pop3-shellnetrc/README.md b/.config/polybar/scripts/inbox-pop3-shellnetrc/README.md
new file mode 100644
index 0000000..a2640c4
--- /dev/null
+++ b/.config/polybar/scripts/inbox-pop3-shellnetrc/README.md
@@ -0,0 +1,22 @@
+# Script: inbox-pop3-shellnetrc
+
+A script that shows if there are unread mails in your POP3 inbox.
+
+This script actually use POP3s. `curl` can also handle unencrypted POP3. You only need to change the protocol in the command.
+
+The login data is stored in a `.netrc`. This is more secure because the password is not visible in the process list.
+
+
+## Dependencies
+
+* `curl`
+
+
+## Module
+
+```ini
+[module/inbox-pop3-shellnetrc]
+type = custom/script
+exec = ~/polybar-scripts/inbox-pop3-shellnetrc.sh
+interval = 60
+```
diff --git a/.config/polybar/scripts/inbox-pop3-shellnetrc/inbox-pop3-shellnetrc.sh b/.config/polybar/scripts/inbox-pop3-shellnetrc/inbox-pop3-shellnetrc.sh
new file mode 100644
index 0000000..d976dd5
--- /dev/null
+++ b/.config/polybar/scripts/inbox-pop3-shellnetrc/inbox-pop3-shellnetrc.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+SERVER=""
+NETRC=".netrc"
+
+inbox=$(curl -sf --netrc-file "$NETRC" pop3s://"$SERVER" | wc -l)
+
+if [ "$inbox" -gt 0 ]; then
+ echo "# $inbox"
+else
+ echo ""
+fi
diff --git a/.config/polybar/scripts/info-airqualityindex/README.md b/.config/polybar/scripts/info-airqualityindex/README.md
new file mode 100644
index 0000000..6c9c2f2
--- /dev/null
+++ b/.config/polybar/scripts/info-airqualityindex/README.md
@@ -0,0 +1,30 @@
+# Script: info-airqualityindex
+
+A script that shows the local World Air Quality Index. It's an indicator for the air pollution.
+
+
+
+
+## Dependencies
+
+* `curl`
+* `jq`
+
+
+## Configuration
+
+You need an API token. [Request one](https://aqicn.org/data-platform/token/).
+
+Choose a city and make sure that the result is what you expect. `berlin` is a valid `CITY` here: http://aqicn.org/city/berlin/. Or use the [map](https://aqicn.org/map/) to find a monitoring station near you. `germany/berlin/friedrichshain-frankfurter-allee` works also as `CITY`.
+
+If `CITY` is left empty, the location is retrieved via the Mozilla Location API.
+
+
+## Module
+
+```ini
+[module/info-airqualityindex]
+type = custom/script
+exec = ~/polybar-scripts/info-airqualityindex.sh
+interval = 600
+```
diff --git a/.config/polybar/scripts/info-airqualityindex/info-airqualityindex.sh b/.config/polybar/scripts/info-airqualityindex/info-airqualityindex.sh
new file mode 100644
index 0000000..f761087
--- /dev/null
+++ b/.config/polybar/scripts/info-airqualityindex/info-airqualityindex.sh
@@ -0,0 +1,41 @@
+#!/bin/sh
+
+TOKEN=""
+CITY=""
+
+API="https://api.waqi.info/feed"
+
+if [ -n "$CITY" ]; then
+ aqi=$(curl -sf "$API/$CITY/?token=$TOKEN")
+else
+ location=$(curl -sf https://location.services.mozilla.com/v1/geolocate?key=geoclue)
+
+ if [ -n "$location" ]; then
+ location_lat="$(echo "$location" | jq '.location.lat')"
+ location_lon="$(echo "$location" | jq '.location.lng')"
+
+ aqi=$(curl -sf "$API/geo:$location_lat;$location_lon/?token=$TOKEN")
+ fi
+fi
+
+if [ -n "$aqi" ]; then
+ if [ "$(echo "$aqi" | jq -r '.status')" = "ok" ]; then
+ aqi=$(echo "$aqi" | jq '.data.aqi')
+
+ if [ "$aqi" -lt 50 ]; then
+ echo "%{F#009966}#%{F-} $aqi"
+ elif [ "$aqi" -lt 100 ]; then
+ echo "%{F#ffde33}#%{F-} $aqi"
+ elif [ "$aqi" -lt 150 ]; then
+ echo "%{F#ff9933}#%{F-} $aqi"
+ elif [ "$aqi" -lt 200 ]; then
+ echo "%{F#cc0033}#%{F-} $aqi"
+ elif [ "$aqi" -lt 300 ]; then
+ echo "%{F#660099}#%{F-} $aqi"
+ else
+ echo "%{F#7e0023}#%{F-} $aqi"
+ fi
+ else
+ echo "$aqi" | jq -r '.data'
+ fi
+fi
diff --git a/.config/polybar/scripts/info-airqualityindex/screenshots/1.png b/.config/polybar/scripts/info-airqualityindex/screenshots/1.png
new file mode 100644
index 0000000..e389abd
Binary files /dev/null and b/.config/polybar/scripts/info-airqualityindex/screenshots/1.png differ
diff --git a/.config/polybar/scripts/info-camera-mic/README.md b/.config/polybar/scripts/info-camera-mic/README.md
new file mode 100644
index 0000000..54a928d
--- /dev/null
+++ b/.config/polybar/scripts/info-camera-mic/README.md
@@ -0,0 +1,15 @@
+# Script: info-camera-mic
+
+A shell script for displaying an indicator of camera and microphone usage.
+
+
+
+
+## Module
+
+```ini
+[module/info-camera-mic]
+type = custom/script
+exec = ~/polybar-scripts/info-camera-mic.sh
+interval = 5
+```
diff --git a/.config/polybar/scripts/info-camera-mic/info-camera-mic.sh b/.config/polybar/scripts/info-camera-mic/info-camera-mic.sh
new file mode 100644
index 0000000..9986ed2
--- /dev/null
+++ b/.config/polybar/scripts/info-camera-mic/info-camera-mic.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+if lsof /dev/video0 >/dev/null 2>&1; then
+ camera="#1"
+fi
+
+if pacmd list-sources 2>&1 | grep -q RUNNING; then
+ mic="#2"
+fi
+
+echo "$camera $mic"
diff --git a/.config/polybar/scripts/info-camera-mic/screenshots/1.png b/.config/polybar/scripts/info-camera-mic/screenshots/1.png
new file mode 100644
index 0000000..8090709
Binary files /dev/null and b/.config/polybar/scripts/info-camera-mic/screenshots/1.png differ
diff --git a/.config/polybar/scripts/info-cava/README.md b/.config/polybar/scripts/info-cava/README.md
new file mode 100644
index 0000000..fd4a2b2
--- /dev/null
+++ b/.config/polybar/scripts/info-cava/README.md
@@ -0,0 +1,29 @@
+# Script: info-cava
+
+A simple script that runs a small audio visualizer using cava on your taskbar
+
+
+
+
+## Dependencies
+
+* [`cava`](https://github.com/karlstav/cava)
+
+
+## Configuration
+
+Configuration can be made by providing the following command line arguments:
+* `-f`|`--framerate FRAMERATE` : Framerate to be used by cava, default is 60.
+* `-b`|`--bars BARS`: Amount of bars, default is 8.
+* `-e`|`--extra_colors EXTRA_COLORS`: Color gradient used on higher values, separated by commas, default is `fdd,fcc,fbb,faa`, spaces and #s are ignored.
+* `-c`|`--channels {stereo,left,right,average}`: Audio channels to be used, defaults to stereo.
+
+
+## Module
+
+```ini
+[module/info-cava]
+type = custom/script
+exec = ~/polybar-scripts/info-cava.py -f 24 -b 12 -e fffdfc,fffafe,ffeafa,ffc3d2 -c average
+tail = true
+```
diff --git a/.config/polybar/scripts/info-cava/info-cava.py b/.config/polybar/scripts/info-cava/info-cava.py
new file mode 100755
index 0000000..01b572b
--- /dev/null
+++ b/.config/polybar/scripts/info-cava/info-cava.py
@@ -0,0 +1,75 @@
+#!/bin/env python3
+import argparse
+import os
+import signal
+import subprocess
+import sys
+import tempfile
+
+if len(sys.argv) > 1 and sys.argv[1] == '--subproc':
+ ramp_list = [' ', '▁', '▂', '▃', '▄', '▅', '▆', '▇', '█']
+ ramp_list.extend(
+ f'%{{F#{color.strip(" #")}}}█%{{F-}}'
+ for color in sys.argv[2].split(',')
+ if color
+ )
+ while True:
+ cava_input = input().strip().split()
+ cava_input = [int(i) for i in cava_input]
+ output = ''
+ for bar in cava_input:
+ if bar < len(ramp_list):
+ output += ramp_list[bar]
+
+ else:
+ output += ramp_list[-1]
+
+ print(output)
+
+parser = argparse.ArgumentParser()
+parser.add_argument('-f', '--framerate', type=int, default=60,
+ help='Framerate to be used by cava, default is 60')
+parser.add_argument('-b', '--bars', type=int, default=8,
+ help='Amount of bars, default is 8')
+parser.add_argument('-e', '--extra_colors', default='fdd,fcc,fbb,faa',
+ help='Color gradient used on higher values, separated by commas, default is')
+parser.add_argument('-c', '--channels', choices=['stereo', 'left', 'right', 'average'],
+ help='Audio channels to be used, defaults to stereo')
+
+opts = parser.parse_args()
+conf_channels = ''
+if opts.channels != 'stereo':
+ conf_channels = (
+ 'channels=mono\n'
+ f'mono_option={opts.channels}'
+ )
+
+conf_ascii_max_range = 12 + len([i for i in opts.extra_colors.split(',') if i])
+
+cava_conf = tempfile.mkstemp('','polybar-cava-conf.')[1]
+with open(cava_conf, 'w') as cava_conf_file:
+ cava_conf_file.write(
+ '[general]\n'
+ f'framerate={opts.framerate}\n'
+ f'bars={opts.bars}\n'
+ '[output]\n'
+ 'method=raw\n'
+ 'data_format=ascii\n'
+ f'ascii_max_range={conf_ascii_max_range}\n'
+ 'bar_delimiter=32\n'
+ + conf_channels
+ )
+
+cava_proc = subprocess.Popen(['cava', '-p', cava_conf], stdout=subprocess.PIPE)
+self_proc = subprocess.Popen(['python3', __file__, '--subproc', opts.extra_colors], stdin=cava_proc.stdout)
+
+def cleanup(sig, frame):
+ os.remove(cava_conf)
+ cava_proc.kill()
+ self_proc.kill()
+ sys.exit(0)
+
+signal.signal(signal.SIGTERM, cleanup)
+signal.signal(signal.SIGINT, cleanup)
+
+self_proc.wait()
diff --git a/.config/polybar/scripts/info-cava/screenshots/1.png b/.config/polybar/scripts/info-cava/screenshots/1.png
new file mode 100644
index 0000000..2502307
Binary files /dev/null and b/.config/polybar/scripts/info-cava/screenshots/1.png differ
diff --git a/.config/polybar/scripts/info-docker/README.md b/.config/polybar/scripts/info-docker/README.md
new file mode 100644
index 0000000..83d1d1a
--- /dev/null
+++ b/.config/polybar/scripts/info-docker/README.md
@@ -0,0 +1,26 @@
+# Script: info-docker
+
+Shows the number of Docker containers in one of the states: `created`, `restarting`, `running`, `removing`, `paused`, `exited`, `dead`
+
+
+
+
+## Configuration
+
+You have to add the `docker` command to the `/etc/sudoers` NOPASSWD of your user:
+
+```ini
+user ALL=(ALL) NOPASSWD: /usr/bin/docker ps -qf status=running
+user ALL=(ALL) NOPASSWD: /usr/bin/docker ps -qf status=exited
+user ALL=(ALL) NOPASSWD: /usr/bin/docker ps -qf status=dead
+```
+
+
+## Module
+
+```ini
+[module/info-docker]
+type = custom/script
+exec = ~/polybar-scripts/info-docker.sh
+interval = 60
+```
diff --git a/.config/polybar/scripts/info-docker/info-docker.sh b/.config/polybar/scripts/info-docker/info-docker.sh
new file mode 100644
index 0000000..8d32baa
--- /dev/null
+++ b/.config/polybar/scripts/info-docker/info-docker.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+STATUS="running exited dead"
+
+for stat in $STATUS; do
+ output="$output $(sudo docker ps -qf status="$stat" | wc -l) |"
+done
+
+echo "|$output"
diff --git a/.config/polybar/scripts/info-docker/screenshots/1.png b/.config/polybar/scripts/info-docker/screenshots/1.png
new file mode 100644
index 0000000..34816b1
Binary files /dev/null and b/.config/polybar/scripts/info-docker/screenshots/1.png differ
diff --git a/.config/polybar/scripts/info-dualshock4/README.md b/.config/polybar/scripts/info-dualshock4/README.md
new file mode 100644
index 0000000..c67ee60
--- /dev/null
+++ b/.config/polybar/scripts/info-dualshock4/README.md
@@ -0,0 +1,20 @@
+# Script: info-dualshock4
+
+A shell script that shows the battery level of a DualShock 4 Controller.
+
+
+
+
+## Configuration
+
+The Icon is from [Font Awesome 5](https://fontawesome.com/icons/playstation?style=brands).
+
+
+## Module
+
+```ini
+[module/battery-dualshock4]
+type= custom/script
+exec = ~/polybar-scripts/info-dualshock4.sh
+interval = 10
+```
diff --git a/.config/polybar/scripts/info-dualshock4/info-dualshock4.sh b/.config/polybar/scripts/info-dualshock4/info-dualshock4.sh
new file mode 100644
index 0000000..8dc0c10
--- /dev/null
+++ b/.config/polybar/scripts/info-dualshock4/info-dualshock4.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+for i in /sys/class/power_supply/sony_controller_battery_*/capacity; do
+ echo "# $(cat /sys/class/power_supply/sony_controller_battery_"$i"/capacity)%"
+done
diff --git a/.config/polybar/scripts/info-dualshock4/screenshots/1.png b/.config/polybar/scripts/info-dualshock4/screenshots/1.png
new file mode 100644
index 0000000..d1f23ba
Binary files /dev/null and b/.config/polybar/scripts/info-dualshock4/screenshots/1.png differ
diff --git a/.config/polybar/scripts/info-ethermine/README.md b/.config/polybar/scripts/info-ethermine/README.md
new file mode 100644
index 0000000..1ec70b4
--- /dev/null
+++ b/.config/polybar/scripts/info-ethermine/README.md
@@ -0,0 +1,18 @@
+# Script: info-ethermine
+
+This script reports the current hashrate (in MH/s) for your ethermine account.
+
+
+## Dependencies
+
+* `python-requests`
+
+
+## Module
+
+```ini
+[module/info-ethermine]
+type = custom/script
+exec = ~/polybar-scripts/info-ethermine.sh
+interval = 60
+```
diff --git a/.config/polybar/scripts/info-ethermine/info-ethermine.py b/.config/polybar/scripts/info-ethermine/info-ethermine.py
new file mode 100644
index 0000000..40a6cfc
--- /dev/null
+++ b/.config/polybar/scripts/info-ethermine/info-ethermine.py
@@ -0,0 +1,12 @@
+#!/usr/bin/env python3
+
+import requests
+
+miner = ""
+
+data = requests.get(f"https://api.ethermine.org/miner/{miner}/dashboard").json()['data']['statistics']
+data = data[-1]
+current_hash_rate = data["currentHashrate"]
+currentMHs = round(current_hash_rate/1e6, 1)
+
+print(f"{currentMHs}MH/s")
diff --git a/.config/polybar/scripts/info-eyestrain/README.md b/.config/polybar/scripts/info-eyestrain/README.md
new file mode 100644
index 0000000..19b6cf9
--- /dev/null
+++ b/.config/polybar/scripts/info-eyestrain/README.md
@@ -0,0 +1,15 @@
+# Script: info-eyestrain
+
+A script for avoiding digital eye strain.
+
+It follows the 20-20-20 rule. The timer displays how long it is until the next break. You can add this to send a notification and play a sound when the time is up.
+
+
+## Module
+
+```ini
+[module/info-eyestrain]
+type = custom/script
+exec = ~/polybar-scripts/info-eyestrain.sh
+interval = 60
+```
diff --git a/.config/polybar/scripts/info-eyestrain/info-eyestrain.sh b/.config/polybar/scripts/info-eyestrain/info-eyestrain.sh
new file mode 100644
index 0000000..587cd54
--- /dev/null
+++ b/.config/polybar/scripts/info-eyestrain/info-eyestrain.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+time=$((20 - $(date '+%-M') % 20))
+
+#if [ $time -eq 20 ]; then
+# notify-send 'Break' &
+# ogg123 beep.ogg &> /dev/null &
+#fi
+
+echo "$time"
diff --git a/.config/polybar/scripts/info-gitlab-pipelines/README.md b/.config/polybar/scripts/info-gitlab-pipelines/README.md
new file mode 100644
index 0000000..4262e3e
--- /dev/null
+++ b/.config/polybar/scripts/info-gitlab-pipelines/README.md
@@ -0,0 +1,25 @@
+# Script: info-gitlab-pipelines
+
+Displays the number of succeeded, running and failed gitlab-pipelines triggered by a user.
+
+
+
+
+## Dependencies
+
+* jq
+
+
+## Configuration
+
+Insert the specific server-url, username and your GitLab token (Settings -> Access Token).
+
+
+## Module
+
+```ini
+[module/info-gitlab-pipelines]
+type = custom/script
+exec = ~/polybar-scripts/info-gitlab-pipelines.sh
+interval = 30
+...
diff --git a/.config/polybar/scripts/info-gitlab-pipelines/gitlab-pipelines.sh b/.config/polybar/scripts/info-gitlab-pipelines/gitlab-pipelines.sh
new file mode 100644
index 0000000..c32cd03
--- /dev/null
+++ b/.config/polybar/scripts/info-gitlab-pipelines/gitlab-pipelines.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+GITLAB_USERNAME=""
+GITLAB_SERVER="https://gitlab.com"
+GITLAB_ACCESS_TOKEN=""
+HOURS_AGO="6"
+
+available_projects=$(curl -sH "Private-Token: $GITLAB_ACCESS_TOKEN" \
+ "$GITLAB_SERVER/api/v4/projects?membership=true" | jq '.[] | .id')
+time=$(date -d "$HOURS_AGO hours ago" -Iseconds)
+
+get_pipelines(){
+ curl -sH "Private-Token: $GITLAB_ACCESS_TOKEN" \
+ "$GITLAB_SERVER/api/v4/projects/$id/pipelines?username=$GITLAB_USERNAME&status=$1&updated_after=$time"| jq length
+}
+
+for id in $available_projects; do
+ success=$((success + $(get_pipelines "success")))
+ running=$((running + $(get_pipelines "running")))
+ failed=$((failed + $(get_pipelines "failed")))
+done
+
+echo "|%{F#7cfc00}$success%{F-}|%{F#ffff00}$running%{F-}|%{F#f00}$failed%{F-}|"
diff --git a/.config/polybar/scripts/info-gitlab-pipelines/screenshots/1.png b/.config/polybar/scripts/info-gitlab-pipelines/screenshots/1.png
new file mode 100644
index 0000000..ecb6c44
Binary files /dev/null and b/.config/polybar/scripts/info-gitlab-pipelines/screenshots/1.png differ
diff --git a/.config/polybar/scripts/info-hackspeed/README.md b/.config/polybar/scripts/info-hackspeed/README.md
new file mode 100644
index 0000000..a548a8f
--- /dev/null
+++ b/.config/polybar/scripts/info-hackspeed/README.md
@@ -0,0 +1,33 @@
+# Script: info-hackspeed
+
+A small script that shows your typing speed. Happy Hacking!
+
+
+
+
+## Dependencies
+
+* `xorg-xinput`
+* `awk`
+* coreutils (`rm`, `stdbuf`, `mktemp`, `stat`, you probably have this)
+
+
+## Configuration
+
+* `KEYBOARD_ID`: name of your keyboard. See Setup above. Default: `AT Translated Set 2 keyboard`
+* `METRIC`: either `cpm` (characters per minute) of `wpm` ([words per minute, 1 word = 5 characters](https://en.wikipedia.org/wiki/Words_per_minute)). Default: `cpm`
+* `FORMAT`: format string according to which the metric will be output. Default: `# %d $METRIC`
+* `INTERVAL`: amount of seconds to gather data. Default: 20
+* `LAYOUT`: keyboard layout, to be able to only count letters and numbers. Currently supported are `qwerty`, `azerty`, `qwertz` and `dvorak`. If you have a different layout, please contribute a condition for it! See the script's source code. Use the special value `dontcare` to count all keys, not just letters and numbers. Default: `qwerty`
+
+If after 20 seconds the value stays at 0 even though you're typing, you may have to configure the name of your keyboard. Change the setting `KEYBOARD_ID` (see Configuration below) in the script. You can find your keyboard description with `xinput list --short`.
+
+
+## Module
+
+```ini
+[module/info-hackspeed]
+type = custom/script
+exec = ~/polybar-scripts/info-hackspeed.sh
+tail = true
+```
diff --git a/.config/polybar/scripts/info-hackspeed/info-hackspeed.sh b/.config/polybar/scripts/info-hackspeed/info-hackspeed.sh
new file mode 100644
index 0000000..999c31e
--- /dev/null
+++ b/.config/polybar/scripts/info-hackspeed/info-hackspeed.sh
@@ -0,0 +1,64 @@
+#!/bin/sh
+# shellcheck disable=SC2016,SC2059
+
+KEYBOARD_ID="AT Translated Set 2 keyboard"
+
+# cpm: characters per minute
+# wpm: words per minute (1 word = 5 characters)
+METRIC=cpm
+FORMAT="# %d $METRIC"
+
+INTERVAL=20
+
+# If you have a keyboard layout that is not listed here yet, create a condition
+# yourself. $3 is the key index. Use `xinput test "AT Translated Set 2 keyboard"`
+# to see key codes in real time. Be sure to open a pull request for your
+# layout's condition!
+LAYOUT=qwerty
+
+case "$LAYOUT" in
+ qwerty) CONDITION='($3 >= 10 && $3 <= 19) || ($3 >= 24 && $3 <= 33) || ($3 >= 37 && $3 <= 53) || ($3 >= 52 && $3 <= 58)'; ;;
+ azerty) CONDITION='($3 >= 10 && $3 <= 19) || ($3 >= 24 && $3 <= 33) || ($3 >= 37 && $3 <= 54) || ($3 >= 52 && $3 <= 57)'; ;;
+ qwertz) CONDITION='($3 >= 10 && $3 <= 20) || ($3 >= 24 && $3 <= 34) || ($3 == 36) || ($3 >= 38 && $3 <= 48) || ($3 >= 52 && $3 <= 58)'; ;;
+ dvorak) CONDITION='($3 >= 10 && $3 <= 19) || ($3 >= 27 && $3 <= 33) || ($3 >= 38 && $3 <= 47) || ($3 >= 53 && $3 <= 61)'; ;;
+ dontcare) CONDITION='1'; ;; # Just register all key presses, not only letters and numbers
+ *) echo "Unsupported layout \"$LAYOUT\""; exit 1; ;;
+esac
+
+# We have to account for the fact we're not listening a whole minute
+multiply_by=60
+divide_by=$INTERVAL
+
+case "$METRIC" in
+ wpm) divide_by=$((divide_by * 5)); ;;
+ cpm) ;;
+ *) echo "Unsupported metric \"$METRIC\""; exit 1; ;;
+esac
+
+hackspeed_cache="$(mktemp -p '' hackspeed_cache.XXXXX)"
+trap 'rm "$hackspeed_cache"' EXIT
+
+# Write a dot to our cache for each key press
+printf '' > "$hackspeed_cache"
+xinput test "$KEYBOARD_ID" | \
+ stdbuf -o0 awk '$1 == "key" && $2 == "press" && ('"$CONDITION"') {printf "."}' >> "$hackspeed_cache" &
+
+while true; do
+ # Ask the kernel how big the file is with the command `stat`. The number we
+ # get is the file size in bytes, which equals the amount of dots the file
+ # contains, and hence how much keys were pressed since the file was last
+ # cleared.
+ lines=$(stat --format %s "$hackspeed_cache")
+
+ # Truncate the cache file so that in the next iteration, we count only new
+ # keypresses
+ printf '' > "$hackspeed_cache"
+
+ # The shell only does integer operations, so make sure to first multiply and
+ # then divide
+ value=$((lines * multiply_by / divide_by))
+
+ printf "$FORMAT\\n" "$value"
+
+ sleep $INTERVAL
+done
diff --git a/.config/polybar/scripts/info-hackspeed/screenshots/1.png b/.config/polybar/scripts/info-hackspeed/screenshots/1.png
new file mode 100644
index 0000000..1a6caaf
Binary files /dev/null and b/.config/polybar/scripts/info-hackspeed/screenshots/1.png differ
diff --git a/.config/polybar/scripts/info-healthchecks.io/README.md b/.config/polybar/scripts/info-healthchecks.io/README.md
new file mode 100644
index 0000000..cd3265e
--- /dev/null
+++ b/.config/polybar/scripts/info-healthchecks.io/README.md
@@ -0,0 +1,31 @@
+# Script: info-healthchecks.io
+
+Shows the health of your services registered with [healthchecks.io](https://healthchecks.io).
+
+
+
+
+## Dependencies
+
+* `jq`
+* `curl`
+
+
+## Configuration
+
+Modify any of the all-caps variables to configure the script:
+* `API_KEY`: Your [healthchecks.io](https://healthchecks.io) API key. These are project specific and can be generated on the project settings page.
+* `CHECK_ENDPOINT`: URL of the checks API endpoint. Change if self-hosting.
+* `STATES`: Array of states to monitor. Available options: `"up" "down" "new" "pending" "grace" "started" "paused"`
+* `COLORS`: Associative array that maps a color to each configured state. Defaults to white (#ffffff).
+* `SHOWN_TAGS`: Array of tags to show. Leave empty to disable filtering based on tags.
+
+
+## Module
+
+```ini
+[module/info-healthchecks.io]
+type = custom/script
+exec = ~/polybar-scripts/info-healthchecks.io.sh
+interval = 60
+```
diff --git a/.config/polybar/scripts/info-healthchecks.io/info-healthchecks.io.sh b/.config/polybar/scripts/info-healthchecks.io/info-healthchecks.io.sh
new file mode 100644
index 0000000..cadd3de
--- /dev/null
+++ b/.config/polybar/scripts/info-healthchecks.io/info-healthchecks.io.sh
@@ -0,0 +1,49 @@
+#!/bin/bash
+
+# Your API Key
+API_KEY=""
+# URL of the checks api endpoint. Change if self-hosting the service.
+CHECK_ENDPOINT="https://healthchecks.io/api/v1/checks/"
+
+# States to track
+# Available options: up down new pending grace started paused
+STATES=("up" "down")
+# Color of each state. Defaults to white (#ffffff).
+declare -A COLORS=( [up]="#7cfc00" [down]="#ff0000" )
+# Leave empty to show all tags
+SHOWN_TAGS=()
+
+function build_url {
+ url=$CHECK_ENDPOINT
+ next_sep="?"
+ for tag in "${SHOWN_TAGS[@]}"; do
+ url+="${next_sep}tag=${tag}"
+ next_sep="&"
+ done
+ echo "$url"
+}
+
+response=$(curl --silent --header "X-Api-Key: ${API_KEY}" "$(build_url)")
+
+declare -A stati
+
+for status in "up" "down"; do
+ stati[$status]=0
+done
+
+for status in $(echo "$response" | jq -r '.checks[].status'); do
+ stati[$status]=$((stati[$status] + 1))
+done
+
+output=""
+for status in "${STATES[@]}"; do
+ count=${stati[$status]}
+ if [ ${COLORS[$status]+_} ]; then
+ color=${COLORS[$status]}
+ else
+ color="#ffffff"
+ fi
+ output+="|%{F${color}}${count}%{F-}"
+done
+
+echo "${output:1}"
diff --git a/.config/polybar/scripts/info-healthchecks.io/screenshots/1.png b/.config/polybar/scripts/info-healthchecks.io/screenshots/1.png
new file mode 100644
index 0000000..716ffbb
Binary files /dev/null and b/.config/polybar/scripts/info-healthchecks.io/screenshots/1.png differ
diff --git a/.config/polybar/scripts/info-hexdate/README.md b/.config/polybar/scripts/info-hexdate/README.md
new file mode 100644
index 0000000..15b2e1e
--- /dev/null
+++ b/.config/polybar/scripts/info-hexdate/README.md
@@ -0,0 +1,15 @@
+# Script: info-hexdate
+
+Print the current date in a hex format.
+
+
+
+
+## Module
+
+```ini
+[module/info-hexdate]
+type = custom/script
+exec = ~/polybar-scripts/info-hexdate.sh
+interval = 60
+```
diff --git a/.config/polybar/scripts/info-hexdate/info-hexdate.sh b/.config/polybar/scripts/info-hexdate/info-hexdate.sh
new file mode 100644
index 0000000..d87385f
--- /dev/null
+++ b/.config/polybar/scripts/info-hexdate/info-hexdate.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+day=$(timedatectl | grep "Local" | cut -d ":" -f2 | cut -d " " -f3 | cut -d "-" -f3)
+month=$(timedatectl | grep "Local" | cut -d ":" -f2 | cut -d " " -f3 | cut -d "-" -f2)
+year=$(timedatectl | grep "Local" | cut -d ":" -f2 | cut -d " " -f3 | cut -d "-" -f1)
+
+day=$(echo "obase=16; $day" | bc)
+month=$(echo "obase=16; $month" | bc)
+year=$(echo "obase=16; $year" | bc)
+
+echo "$day-$month-$year"
diff --git a/.config/polybar/scripts/info-hexdate/screenshots/1.png b/.config/polybar/scripts/info-hexdate/screenshots/1.png
new file mode 100644
index 0000000..1212913
Binary files /dev/null and b/.config/polybar/scripts/info-hexdate/screenshots/1.png differ
diff --git a/.config/polybar/scripts/info-hlwm-workspaces/README.md b/.config/polybar/scripts/info-hlwm-workspaces/README.md
new file mode 100644
index 0000000..2ac790f
--- /dev/null
+++ b/.config/polybar/scripts/info-hlwm-workspaces/README.md
@@ -0,0 +1,27 @@
+# Script: info-hlwm-workspaces
+
+Displays all herbstluftwm workspaces with support for all workspace states (`focused`, `visible`, `occupied`, `empty`, `urgent`).
+
+
+
+
+## Dependencies
+
+* `herbstluftwm` running as your WM
+
+
+## Configuration
+
+On its own the script is pretty plain as there are no colors. There are a bunch of TODO comments where you can `echo` [Formatting Tags](https://github.com/jaagr/polybar/wiki/Formatting#format-tags) for certain workspace state to make it more colorful and help you actually distinguish the different states.
+
+
+## Module
+
+```ini
+[module/info-hlwm-workspaces]
+type = custom/script
+exec = ~/polybar-scripts/info-hlwm-workspaces.sh
+tail = true
+scroll-up = herbstclient use_index -1 --skip-visible &
+scroll-down = herbstclient use_index +1 --skip-visible &
+```
diff --git a/.config/polybar/scripts/info-hlwm-workspaces/info-hlwm-workspaces.sh b/.config/polybar/scripts/info-hlwm-workspaces/info-hlwm-workspaces.sh
new file mode 100644
index 0000000..1170d61
--- /dev/null
+++ b/.config/polybar/scripts/info-hlwm-workspaces/info-hlwm-workspaces.sh
@@ -0,0 +1,64 @@
+#!/usr/bin/env bash
+
+# Multi monitor support. Needs MONITOR environment variable to be set for each instance of polybar
+# If MONITOR environment variable is not set this will default to monitor 0
+# Check https://github.com/polybar/polybar/issues/763
+MON_IDX="0"
+mapfile -t MONITOR_LIST < <(polybar --list-monitors | cut -d":" -f1)
+for (( i=0; i<$((${#MONITOR_LIST[@]})); i++ )); do
+ [[ ${MONITOR_LIST[${i}]} == "$MONITOR" ]] && MON_IDX="$i"
+done;
+
+herbstclient --idle "tag_*" 2>/dev/null | {
+
+ while true; do
+ # Read tags into $tags as array
+ IFS=$'\t' read -ra tags <<< "$(herbstclient tag_status "${MON_IDX}")"
+ {
+ for i in "${tags[@]}" ; do
+ # Read the prefix from each tag and render them according to that prefix
+ case ${i:0:1} in
+ '.')
+ # the tag is empty
+ # TODO Add your formatting tags
+ ;;
+ ':')
+ # the tag is not empty
+ # TODO Add your formatting tags
+ ;;
+ '+')
+ # the tag is viewed on the specified MONITOR, but this monitor is not focused.
+ # TODO Add your formatting tags
+ ;;
+ '#')
+ # the tag is viewed on the specified MONITOR and it is focused.
+ # TODO Add your formatting tags
+ ;;
+ '-')
+ # the tag is viewed on a different MONITOR, but this monitor is not focused.
+ # TODO Add your formatting tags
+ ;;
+ '%')
+ # the tag is viewed on a different MONITOR and it is focused.
+ # TODO Add your formatting tags
+ ;;
+ '!')
+ # the tag contains an urgent window
+ # TODO Add your formatting tags
+ ;;
+ esac
+
+ # focus the monitor of the current bar before switching tags
+ echo "%{A1:herbstclient focus_monitor ${MON_IDX}; herbstclient use ${i:1}:} ${i:1} %{A -u -o F- B-}"
+ done
+
+ # reset foreground and background color to default
+ echo "%{F-}%{B-}"
+ } | tr -d "\n"
+
+ echo
+
+ # wait for next event from herbstclient --idle
+ read -r || break
+done
+} 2>/dev/null
diff --git a/.config/polybar/scripts/info-hlwm-workspaces/screenshots/1.png b/.config/polybar/scripts/info-hlwm-workspaces/screenshots/1.png
new file mode 100644
index 0000000..b08e68a
Binary files /dev/null and b/.config/polybar/scripts/info-hlwm-workspaces/screenshots/1.png differ
diff --git a/.config/polybar/scripts/info-kernel/README.md b/.config/polybar/scripts/info-kernel/README.md
new file mode 100644
index 0000000..b263a20
--- /dev/null
+++ b/.config/polybar/scripts/info-kernel/README.md
@@ -0,0 +1,13 @@
+# Script: info-kernel
+
+A script that shows the running kernel version.
+
+
+## Module
+
+```ini
+[module/info-kernel]
+type = custom/script
+exec = uname -r
+interval = 1024
+```
diff --git a/.config/polybar/scripts/info-pingrtt/README.md b/.config/polybar/scripts/info-pingrtt/README.md
new file mode 100644
index 0000000..6bccea0
--- /dev/null
+++ b/.config/polybar/scripts/info-pingrtt/README.md
@@ -0,0 +1,17 @@
+# Script: info-pingrtt
+
+A script that displays a ping result. It also shows a colored icon.
+
+
+
+
+
+
+## Module
+
+```ini
+[module/info-pingrtt]
+type = custom/script
+exec = ~/polybar-scripts/info-pingrtt.sh
+interval = 10
+```
diff --git a/.config/polybar/scripts/info-pingrtt/info-pingrtt.sh b/.config/polybar/scripts/info-pingrtt/info-pingrtt.sh
new file mode 100644
index 0000000..eb49464
--- /dev/null
+++ b/.config/polybar/scripts/info-pingrtt/info-pingrtt.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+HOST=127.43.12.64
+
+if ! ping=$(ping -n -c 1 -W 1 $HOST); then
+ echo "# ping failed"
+else
+ rtt=$(echo "$ping" | sed -rn 's/.*time=([0-9]{1,})\.?[0-9]{0,} ms.*/\1/p')
+
+ if [ "$rtt" -lt 50 ]; then
+ icon="%{F#3cb703}#%{F-}"
+ elif [ "$rtt" -lt 150 ]; then
+ icon="%{F#f9dd04}#%{F-}"
+ else
+ icon="%{F#d60606}#%{F-}"
+ fi
+
+ echo "$icon $rtt ms"
+fi
diff --git a/.config/polybar/scripts/info-pingrtt/screenshots/1.png b/.config/polybar/scripts/info-pingrtt/screenshots/1.png
new file mode 100644
index 0000000..371a4ee
Binary files /dev/null and b/.config/polybar/scripts/info-pingrtt/screenshots/1.png differ
diff --git a/.config/polybar/scripts/info-pingrtt/screenshots/2.png b/.config/polybar/scripts/info-pingrtt/screenshots/2.png
new file mode 100644
index 0000000..ba364bc
Binary files /dev/null and b/.config/polybar/scripts/info-pingrtt/screenshots/2.png differ
diff --git a/.config/polybar/scripts/info-pingrtt/screenshots/3.png b/.config/polybar/scripts/info-pingrtt/screenshots/3.png
new file mode 100644
index 0000000..a14d06e
Binary files /dev/null and b/.config/polybar/scripts/info-pingrtt/screenshots/3.png differ
diff --git a/.config/polybar/scripts/info-podman/README.md b/.config/polybar/scripts/info-podman/README.md
new file mode 100644
index 0000000..1339826
--- /dev/null
+++ b/.config/polybar/scripts/info-podman/README.md
@@ -0,0 +1,19 @@
+# Script: info-podman
+
+Shows the number of Podman containers in one of the states: `created`, `exited`, `paused`, `running`, `unknown`
+
+
+
+
+## Dependencies
+
+* [`podman`](https://github.com/containers/podman)
+
+
+## Module
+```ini
+[module/info-podman]
+type = custom/script
+exec = ~/polybar-scripts/info-podman.sh
+interval = 60
+```
diff --git a/.config/polybar/scripts/info-podman/info-podman.sh b/.config/polybar/scripts/info-podman/info-podman.sh
new file mode 100644
index 0000000..d657875
--- /dev/null
+++ b/.config/polybar/scripts/info-podman/info-podman.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+STATUS="created exited paused running unknown"
+
+for stat in $STATUS; do
+ output="$output $(podman ps -qf status="$stat" | wc -l) |"
+done
+
+echo "|$output"
diff --git a/.config/polybar/scripts/info-podman/screenshots/1.png b/.config/polybar/scripts/info-podman/screenshots/1.png
new file mode 100644
index 0000000..fd7f541
Binary files /dev/null and b/.config/polybar/scripts/info-podman/screenshots/1.png differ
diff --git a/.config/polybar/scripts/info-projecthamster/README.md b/.config/polybar/scripts/info-projecthamster/README.md
new file mode 100644
index 0000000..300a740
--- /dev/null
+++ b/.config/polybar/scripts/info-projecthamster/README.md
@@ -0,0 +1,15 @@
+# Script: info-projecthamster
+
+This script displays Hamster Time Tracker information.
+
+
+
+
+## Module
+
+```ini
+[module/info-projecthamster]
+type = custom/script
+exec = ~/polybar-scripts/info-projecthamster.sh
+interval = 5
+```
diff --git a/.config/polybar/scripts/info-projecthamster/info-projecthamster.sh b/.config/polybar/scripts/info-projecthamster/info-projecthamster.sh
new file mode 100644
index 0000000..a836d72
--- /dev/null
+++ b/.config/polybar/scripts/info-projecthamster/info-projecthamster.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+activity=$(hamster current 2> /dev/null | cut -d " " -f 3- | sed 's/@.* / - /')
+
+if [ -n "$activity" ]; then
+ echo "$activity"
+else
+ echo "No Activity"
+fi
diff --git a/.config/polybar/scripts/info-projecthamster/screenshots/1.png b/.config/polybar/scripts/info-projecthamster/screenshots/1.png
new file mode 100644
index 0000000..5f25883
Binary files /dev/null and b/.config/polybar/scripts/info-projecthamster/screenshots/1.png differ
diff --git a/.config/polybar/scripts/info-redshift-temp/README.md b/.config/polybar/scripts/info-redshift-temp/README.md
new file mode 100644
index 0000000..bec1121
--- /dev/null
+++ b/.config/polybar/scripts/info-redshift-temp/README.md
@@ -0,0 +1,15 @@
+# Script: info-redshift-temp
+
+This script displays the current color temperature.
+
+
+
+
+## Module
+
+```ini
+[module/info-redshift-temp]
+type = custom/script
+exec = ~/polybar-scripts/info-redshift-temp.sh
+interval = 5
+```
diff --git a/.config/polybar/scripts/info-redshift-temp/info-redshift-temp.sh b/.config/polybar/scripts/info-redshift-temp/info-redshift-temp.sh
new file mode 100644
index 0000000..47784ba
--- /dev/null
+++ b/.config/polybar/scripts/info-redshift-temp/info-redshift-temp.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+if [ "$(pgrep -x redshift)" ]; then
+ temp=$(redshift -p 2> /dev/null | grep temp | cut -d ":" -f 2 | tr -dc "[:digit:]")
+
+ if [ -z "$temp" ]; then
+ echo "%{F#65737E} #"
+ elif [ "$temp" -ge 5000 ]; then
+ echo "%{F#8FA1B3} #"
+ elif [ "$temp" -ge 4000 ]; then
+ echo "%{F#EBCB8B} #"
+ else
+ echo "%{F#D08770} #"
+ fi
+fi
diff --git a/.config/polybar/scripts/info-redshift-temp/screenshots/1.png b/.config/polybar/scripts/info-redshift-temp/screenshots/1.png
new file mode 100644
index 0000000..7e13aae
Binary files /dev/null and b/.config/polybar/scripts/info-redshift-temp/screenshots/1.png differ
diff --git a/.config/polybar/scripts/info-softwarecounter/README.md b/.config/polybar/scripts/info-softwarecounter/README.md
new file mode 100644
index 0000000..7768cb2
--- /dev/null
+++ b/.config/polybar/scripts/info-softwarecounter/README.md
@@ -0,0 +1,25 @@
+# Script: info-softwarecounter
+
+A script that counts the number of specified running software including GUIs and processes.
+
+Options to only monitor GUI applications or only processes exist. Users can add their own applications or processes they wish to watch simply by updating the existing dictionaries at the start of the script.
+
+Arbitrary program counts can be combined, for example, the vim/nvim or chrome/chromium counts can be added together and the total displayed.
+
+
+
+
+## Dependencies
+
+* `wmctrl`
+* `pgrep`
+
+
+## Module
+
+```
+[module/info-softwarecounter]
+type = custom/script
+exec = ~/polybar-scripts/info-softwarecounter.py
+interval = 10
+```
diff --git a/.config/polybar/scripts/info-softwarecounter/info-softwarecounter.py b/.config/polybar/scripts/info-softwarecounter/info-softwarecounter.py
new file mode 100644
index 0000000..a4ea667
--- /dev/null
+++ b/.config/polybar/scripts/info-softwarecounter/info-softwarecounter.py
@@ -0,0 +1,223 @@
+#!/usr/bin/env python3
+
+import subprocess
+from collections import Counter, OrderedDict
+import logging
+
+
+# update GUIs
+GUI = True
+
+# update processes
+PROCESS = True
+
+# Debugging feature
+DEBUG = False
+
+
+logger = logging.getLogger(__name__)
+if DEBUG:
+ FORMAT = '%(asctime)s - %(levelname)s - %(funcName)s:%(lineno)d - %(message)s'
+ logger.setLevel(logging.DEBUG)
+ fh = logging.FileHandler(
+ filename='./info-softwarecounter.log',
+ encoding='utf-8'
+ )
+ fh.setLevel(logging.DEBUG)
+ fh.setFormatter(logging.Formatter(FORMAT))
+ logger.addHandler(fh)
+
+
+# _____ _ _ _____
+# / ____| | | |_ _|
+# | | __| | | | | |
+# | | |_ | | | | | |
+# | |__| | |__| |_| |_
+# \_____|\____/|_____|
+
+
+# program/process names and corresponding gylphs
+guis = OrderedDict({
+ 'terminals': '#',
+ 'chromes': '#',
+ 'firefox': '#',
+ 'skypeforlinux': '#',
+ 'filemanager': '#',
+ 'remote-desktop': '#',
+ 'pdfviewer': '#',
+ 'image': '#',
+})
+
+# combine counts of program/process names in the tuple
+# the resulting glpyh used will be that of the corresponding key
+combine_guis = {
+ 'terminals': ('gnome-terminal-server', 'xfce4-terminal', 'alacritty', 'termite', 'terminator', 'urxvt'),
+ 'chromes': ('chromium', 'chrome'),
+ 'filemanager': ('nemo', 'thunar', 'dolphin', 'nautilus', 'pcmanfm'),
+ 'remote-desktop': ('TeamViewer', ),
+ 'pdfviewer': ('evince', 'okular', 'zathura'),
+ 'image': ('gthumb', 'shotwell', 'deepin-image-vi', 'eog', 'gimp-2.10'),
+}
+
+
+def get(cmd):
+ return subprocess.check_output(cmd).decode("utf-8").strip()
+
+
+# def check_wtype(w_id):
+# # check the type of window, only list "NORMAL" windows
+# return "_NET_WM_WINDOW_TYPE_NORMAL" in get(["xprop", "-id", w_id])
+
+
+def get_process(w_id):
+ # get the name of the process, owning the window
+ proc = get(["ps", "-p", w_id, "-o", "cmd="])
+ return proc.split()[0].split("/")[-1]
+
+
+def get_running_guis():
+
+ wlist = [
+ line.split() for line in subprocess.check_output(
+ ["wmctrl", "-lp"]
+ ).decode("utf-8").splitlines()
+ ]
+
+ logger.debug("wlist after LC:")
+ logger.debug("---------")
+ for i in wlist:
+ logger.debug(i)
+ logger.debug("---------")
+
+ validprocs = [
+ get_process(w[2]) for w in wlist if w[2] != '0' # and check_wtype(w[0])
+ ]
+
+ logger.debug(f"validprocs -> {validprocs}")
+ return validprocs
+
+
+def GUI(gui_output=''):
+
+ # get list of running GUI programs
+ gui_counts = Counter(get_running_guis())
+ logger.debug(f"gui_counts -> {gui_counts}")
+
+ logger.debug("combine_guis items:")
+ logger.debug("---------")
+ # combine programs in program combine list
+ for k, lst in combine_guis.items():
+ logger.debug(f"{k} -> {lst}")
+ count = 0
+ for i in lst:
+ try:
+ count += gui_counts.pop(i)
+ except KeyError:
+ pass
+ if count:
+ gui_counts[k] += count
+ logger.debug("---------")
+ logger.debug(f"gui_counts after for loop -> {gui_counts}")
+
+ logger.debug("guis items:")
+ logger.debug("---------")
+ # generate program output
+ for k, v in guis.items():
+ logger.debug(f"{k} -> {v}")
+ try:
+ logger.debug(f"k, gui_counts[k] -> {k}, {gui_counts[k]}")
+ c = gui_counts[k]
+ if c:
+ gui_output += '%s %i ' % (v, c)
+ except Exception:
+ pass
+ logger.debug("---------")
+
+ logger.debug(f"gui_output -> {gui_output}")
+ return gui_output
+
+
+# _____ _____ ____ _____ ______ _____ _____
+# | __ \| __ \ / __ \ / ____| ____|/ ____/ ____|
+# | |__) | |__) | | | | | | |__ | (___| (___
+# | ___/| _ /| | | | | | __| \___ \\___ \
+# | | | | \ \| |__| | |____| |____ ____) |___) |
+# |_| |_| \_\\____/ \_____|______|_____/_____/
+
+
+processes = OrderedDict({
+ 'vims': '#',
+ 'ssh': '#',
+ 'updater': '#',
+})
+
+combine_proccesses = {
+ 'vims': ('nvim', 'vim', 'atom'),
+ 'updater': ('pacman', 'yay', 'trizen', 'yaourt', 'makepkg', 'auracle'),
+}
+
+
+def get_running_proc(process_name_list):
+ counts = [None] * len(process_name_list)
+
+ for i, p in enumerate(process_name_list):
+ try:
+ count = int(
+ subprocess.check_output(
+ ['pgrep', '-c', '-x', p]
+ ).decode('utf-8')
+ )
+ except subprocess.CalledProcessError:
+ count = 0
+
+ counts[i] = (p, count)
+ return dict(counts)
+
+
+def PROCESS(process_output=''):
+
+ # count running proccesses
+ process_counts = get_running_proc(processes.keys())
+ combine_counts = get_running_proc(
+ list(sum(combine_proccesses.values(), ())))
+ process_counts.update(combine_counts)
+
+ # combine processes in process combine list
+ for k, lst in combine_proccesses.items():
+ count = 0
+ for i in lst:
+ try:
+ count += process_counts.pop(i)
+ except KeyError:
+ pass
+ if count:
+ process_counts[k] += count
+
+ # generate process output
+ for k, v in processes.items():
+ try:
+ c = process_counts[k]
+ if c:
+ process_output += '%s %i ' % (v, c)
+ except Exception:
+ pass
+
+ logger.debug(f"process_output -> {process_output}")
+ return process_output
+
+
+def main():
+
+ if GUI:
+ gui_output = GUI()
+
+ if PROCESS:
+ process_output = PROCESS()
+
+ print(gui_output + process_output)
+
+
+if __name__ == "__main__":
+ logger.debug("------------ Script runs ------------")
+ main()
+ logger.debug("------------ Script stops ------------\n")
diff --git a/.config/polybar/scripts/info-softwarecounter/screenshots/1.png b/.config/polybar/scripts/info-softwarecounter/screenshots/1.png
new file mode 100644
index 0000000..35d879d
Binary files /dev/null and b/.config/polybar/scripts/info-softwarecounter/screenshots/1.png differ
diff --git a/.config/polybar/scripts/info-ssh-sessions/README.md b/.config/polybar/scripts/info-ssh-sessions/README.md
new file mode 100644
index 0000000..a5dfed3
--- /dev/null
+++ b/.config/polybar/scripts/info-ssh-sessions/README.md
@@ -0,0 +1,20 @@
+# Script: info-ssh-sessions
+
+A script that displays the count of current ssh sessions as well as the public IP address of the fist session.
+
+
+
+
+## Dependencies
+
+* `lsof`
+
+
+## Module
+
+```ini
+[module/info-ssh-sessions]
+type = custom/script
+exec = ~/polybar-scripts/info-ssh-sessions.sh
+interval = 5
+```
diff --git a/.config/polybar/scripts/info-ssh-sessions/info-ssh-sessions.sh b/.config/polybar/scripts/info-ssh-sessions/info-ssh-sessions.sh
new file mode 100644
index 0000000..870faaa
--- /dev/null
+++ b/.config/polybar/scripts/info-ssh-sessions/info-ssh-sessions.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+sessions="$(lsof -Pi | grep ":22")"
+
+if [ -n "$sessions" ]; then
+ count=$(echo "$sessions" | wc -l)
+ echo "# ($count): $(echo "$sessions" | cut -d ">" -f 2 | cut -d " " -f 1 | cut -d ":" -f 1 | tail -n 1)"
+else
+ echo "# (0)"
+fi
diff --git a/.config/polybar/scripts/info-ssh-sessions/screenshots/1.png b/.config/polybar/scripts/info-ssh-sessions/screenshots/1.png
new file mode 100644
index 0000000..0c55daa
Binary files /dev/null and b/.config/polybar/scripts/info-ssh-sessions/screenshots/1.png differ
diff --git a/.config/polybar/scripts/info-taskspooler/README.md b/.config/polybar/scripts/info-taskspooler/README.md
new file mode 100644
index 0000000..b168145
--- /dev/null
+++ b/.config/polybar/scripts/info-taskspooler/README.md
@@ -0,0 +1,28 @@
+# Script: info-taskspooler
+
+A small script that displays the number of queues/runtimes for one or more task spooler servers.
+
+
+
+
+## Dependencies
+
+* `task-spooler`
+
+
+## Configuration
+
+By default the script will output the count of the default task-spooler server.
+
+Arguments can be passed to show custom task-spooler servers by using the `TS_SOCKET variable`. These custom servers will need to use a socket filename format like /tmp/ts-socket.SOCK_NAME or the script will be unable to find the server. Arguments are passed as `name,sock_name` with sock_name being optional, e.g. `default yt,youtube p,podcast`.
+
+
+## Module
+
+```ini
+[module/info-taskspooler]
+type = custom/script
+exec = ~/polybar-scripts/info-task-spooler/info-taskspooler.sh
+# exec = ~/polybar-scripts/info-taskspooler/info-taskspooler.sh default yt,youtube p,podcast
+interval = 5
+```
diff --git a/.config/polybar/scripts/info-taskspooler/info-taskspooler.sh b/.config/polybar/scripts/info-taskspooler/info-taskspooler.sh
new file mode 100644
index 0000000..c3df808
--- /dev/null
+++ b/.config/polybar/scripts/info-taskspooler/info-taskspooler.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+# USAGE:
+# No arguments: prints the job running/queued job count of the default tsp server
+# Arguments: name,sock_name - one or more arguments, e.g. tsp yt,youtube p,podcasts
+# sock_name is optional, will default to default tsp socket
+# custom socket names will be generated as /tmp/ts-socket.SOCK_NAME, your TS_SOCKET will need to match
+
+get_tsp_count() {
+ sock=/tmp/socket-ts.${1:-$(id -u)}
+
+ tsp_count=$(TS_SOCKET=$sock tsp|grep -E -c 'running|queued')
+ echo "${tsp_count:-0}"
+}
+
+# without argument, just show count of default socket
+if [ $# -lt 1 ]; then
+ get_tsp_count
+else
+ for t in "$@"; do
+ IFS=, read -r name sock_name <<- EOF
+ ${t}
+ EOF
+
+ echo "${name} $(get_tsp_count "${sock_name}")"
+ done|sed 'N;s/\n/ /'
+fi
diff --git a/.config/polybar/scripts/info-taskspooler/screenshots/1.png b/.config/polybar/scripts/info-taskspooler/screenshots/1.png
new file mode 100644
index 0000000..f273e2b
Binary files /dev/null and b/.config/polybar/scripts/info-taskspooler/screenshots/1.png differ
diff --git a/.config/polybar/scripts/info-timew/README.md b/.config/polybar/scripts/info-timew/README.md
new file mode 100644
index 0000000..c4edfce
--- /dev/null
+++ b/.config/polybar/scripts/info-timew/README.md
@@ -0,0 +1,16 @@
+# Script: info-timew
+
+This script displays the daily tracked time. You can click it, to start tracking, using timew.
+
+You can use the `--weekday` toggle, to view daily or weekly time spend. (may take the `interval` time to update)
+
+## Module
+
+```ini
+[module/info-timew]
+type = custom/script
+exec = ~/polybar-scripts/info-timew.sh
+interval = 10
+click-left = ~/polybar-scripts/info-timew.sh --toggle
+click-right = ~/polybar-scripts/info-timew.sh --weekday
+```
diff --git a/.config/polybar/scripts/info-timew/info-timew.sh b/.config/polybar/scripts/info-timew/info-timew.sh
new file mode 100644
index 0000000..c8cdd18
--- /dev/null
+++ b/.config/polybar/scripts/info-timew/info-timew.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+MODE_FILE="$HOME/.config/polybar/info-timew.mode"
+
+if [ ! -f "${MODE_FILE}" ]; then
+ touch "${MODE_FILE}"
+ echo "d" > "${MODE_FILE}"
+fi
+
+ACTUAL_MODE=$(cat "${MODE_FILE}")
+
+if timew > /dev/null 2>&1; then
+ if [ "$ACTUAL_MODE" = "w" ]; then
+ printf '%s/week' "$(timew summary :week | awk '{print $NF}' | tail -2 | head -1)"
+ else
+ printf '%s/day' "$(timew summary :day | awk '{print $NF}' | tail -2 | head -1)"
+ fi
+else
+ printf "no tracking"
+fi
+
+
+
+if [ "${1}" = "--weekday" ]; then
+ if [ "$ACTUAL_MODE" = "w" ]; then
+ echo "d" > "${MODE_FILE}"
+ else
+ echo "w" > "${MODE_FILE}"
+
+ fi
+fi
+
+
+if [ "${1}" = "--toggle" ]; then
+ if timew; then
+ timew stop;
+ else
+ timew start;
+ fi
+fi
diff --git a/.config/polybar/scripts/info-timezone/README.md b/.config/polybar/scripts/info-timezone/README.md
new file mode 100644
index 0000000..2985436
--- /dev/null
+++ b/.config/polybar/scripts/info-timezone/README.md
@@ -0,0 +1,16 @@
+# Script: info-timezone
+
+A custom polybar script to switch the timezone of the date displayed.
+
+
+
+
+## Module
+
+```ini
+[module/info-timezone]
+type = custom/script
+exec = ~/polybar-scripts/info-timezone.sh
+tail = true
+click-left = kill -USR1 %pid%
+```
diff --git a/.config/polybar/scripts/info-timezone/info-timezone.sh b/.config/polybar/scripts/info-timezone/info-timezone.sh
new file mode 100644
index 0000000..10a5751
--- /dev/null
+++ b/.config/polybar/scripts/info-timezone/info-timezone.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+# Change format here. see `man date` for format controls.
+FORMAT="%I:%M %p"
+
+# Add the timezones of your choice. see `timedatectl list-timezones`.
+set -- "UTC-0" "Australia/Sydney" "Asia/Kolkata" "America/Chicago"
+
+TIMEZONES_LENGTH=$#
+current_idx=1
+
+print_date() {
+ TZ=${current_timezone:?} date +"${FORMAT}" | echo "${current_timezone:?}: $(cat -)"
+}
+
+update_current_timezone() {
+ current_idx=$(($((current_idx+1)) % $(("$TIMEZONES_LENGTH"+1))))
+ if [ $current_idx -lt 1 ]; then
+ current_idx=1
+ fi
+}
+
+click() {
+ update_current_timezone
+ print_date
+}
+
+trap "click" USR1
+
+while true; do
+ eval "current_timezone=\${$current_idx}"
+ print_date current_timezone
+ sleep 5 &
+ wait
+done
diff --git a/.config/polybar/scripts/info-timezone/screenshots/1.gif b/.config/polybar/scripts/info-timezone/screenshots/1.gif
new file mode 100644
index 0000000..27e5c80
Binary files /dev/null and b/.config/polybar/scripts/info-timezone/screenshots/1.gif differ
diff --git a/.config/polybar/scripts/info-tmux-sessions/README.md b/.config/polybar/scripts/info-tmux-sessions/README.md
new file mode 100644
index 0000000..cc3f75a
--- /dev/null
+++ b/.config/polybar/scripts/info-tmux-sessions/README.md
@@ -0,0 +1,16 @@
+# Script: info-tmux-sessions
+
+A simple script to show tmux sessions.
+
+
+
+
+
+## Module
+
+```ini
+[module/info-tmux-sessions]
+type = custom/script
+exec = ~/polybar-scripts/info-tmux-sessions.sh
+interval = 5
+```
diff --git a/.config/polybar/scripts/info-tmux-sessions/info-tmux-sessions.sh b/.config/polybar/scripts/info-tmux-sessions/info-tmux-sessions.sh
new file mode 100644
index 0000000..41b4d56
--- /dev/null
+++ b/.config/polybar/scripts/info-tmux-sessions/info-tmux-sessions.sh
@@ -0,0 +1,21 @@
+#! /bin/sh
+
+if sessionlist=$(tmux ls 2>/dev/null); then
+ printf "# "
+
+ echo "$sessionlist" | while read -r line; do
+ session=$(echo "$line" | cut -d ':' -f 1)
+
+ if echo "$line" | grep -q "(attached)"; then
+ status="(a)"
+ else
+ status=""
+ fi
+
+ printf "%s%s " "$session" "$status"
+ done
+
+ printf "\n"
+else
+ printf "# none\n"
+fi
diff --git a/.config/polybar/scripts/info-tmux-sessions/screenshots/1.png b/.config/polybar/scripts/info-tmux-sessions/screenshots/1.png
new file mode 100644
index 0000000..27a4aee
Binary files /dev/null and b/.config/polybar/scripts/info-tmux-sessions/screenshots/1.png differ
diff --git a/.config/polybar/scripts/info-tmux-sessions/screenshots/2.png b/.config/polybar/scripts/info-tmux-sessions/screenshots/2.png
new file mode 100644
index 0000000..ff60e4c
Binary files /dev/null and b/.config/polybar/scripts/info-tmux-sessions/screenshots/2.png differ
diff --git a/.config/polybar/scripts/info-todotxt/README.md b/.config/polybar/scripts/info-todotxt/README.md
new file mode 100644
index 0000000..fb7a925
--- /dev/null
+++ b/.config/polybar/scripts/info-todotxt/README.md
@@ -0,0 +1,15 @@
+# Script: info-todotxt
+
+A script that shows todo.txt items due. The first column shows items due today, and the second column shows items due this week (including today).
+
+
+
+
+## Module
+
+```ini
+[module/info-todotxt]
+type = custom/script
+exec = ~/polybar-scripts/info-todotxt.sh
+interval = 60
+```
diff --git a/.config/polybar/scripts/info-todotxt/info-todotxt.sh b/.config/polybar/scripts/info-todotxt/info-todotxt.sh
new file mode 100644
index 0000000..3aae741
--- /dev/null
+++ b/.config/polybar/scripts/info-todotxt/info-todotxt.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+duetoday=$(grep "due:$(date -I)" ~/todo.txt | grep -c -v "x")
+dueweek=0
+weekday=0
+
+while [ "$weekday" -le 7 ]; do
+ dueweek=$((dueweek + $(grep "due:$(date -I --date="$weekday day")" ~/todo.txt | grep -c -v "x")))
+ weekday=$(( weekday + 1 ))
+done
+
+if [ "$dueweek" -gt 0 ]; then
+ echo "#1 $duetoday $dueweek"
+else
+ echo "#2"
+fi
\ No newline at end of file
diff --git a/.config/polybar/scripts/info-todotxt/screenshots/1.png b/.config/polybar/scripts/info-todotxt/screenshots/1.png
new file mode 100644
index 0000000..f1903ed
Binary files /dev/null and b/.config/polybar/scripts/info-todotxt/screenshots/1.png differ
diff --git a/.config/polybar/scripts/info-trash/README.md b/.config/polybar/scripts/info-trash/README.md
new file mode 100644
index 0000000..6981316
--- /dev/null
+++ b/.config/polybar/scripts/info-trash/README.md
@@ -0,0 +1,16 @@
+# Script: info-trash
+
+This script count the files in you trash directory.
+
+
+
+
+## Module
+
+```ini
+[module/info-trash]
+type = custom/script
+exec = ~/polybar-scripts/info-trash.sh
+interval = 60
+click-left = ~/polybar-scripts/info-trash.sh --clean &
+```
diff --git a/.config/polybar/scripts/info-trash/info-trash.sh b/.config/polybar/scripts/info-trash/info-trash.sh
new file mode 100644
index 0000000..09a50ea
--- /dev/null
+++ b/.config/polybar/scripts/info-trash/info-trash.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+case "$1" in
+ --clean)
+ rm -rf ~/.local/share/Trash/files
+ rm -rf ~/.local/share/Trash/info
+ mkdir ~/.local/share/Trash/files
+ mkdir ~/.local/share/Trash/info
+ ;;
+ *)
+ find ~/.local/share/Trash/files/ -maxdepth 1 | wc -l
+ ;;
+esac
diff --git a/.config/polybar/scripts/info-trash/screenshots/1.png b/.config/polybar/scripts/info-trash/screenshots/1.png
new file mode 100644
index 0000000..e1403a0
Binary files /dev/null and b/.config/polybar/scripts/info-trash/screenshots/1.png differ
diff --git a/.config/polybar/scripts/info-usbtoserial/95-usbtoserial.rules b/.config/polybar/scripts/info-usbtoserial/95-usbtoserial.rules
new file mode 100644
index 0000000..0d9931a
--- /dev/null
+++ b/.config/polybar/scripts/info-usbtoserial/95-usbtoserial.rules
@@ -0,0 +1,4 @@
+ACTION=="add", SUBSYSTEM=="tty"
+ RUN+="/home/user/.config/polybar/info-usbtoserial.sh --update"
+ACTION=="remove", SUBSYSTEM=="tty"
+ RUN+="/home/user/.config/polybar/info-usbtoserial.sh --update"
diff --git a/.config/polybar/scripts/info-usbtoserial/README.md b/.config/polybar/scripts/info-usbtoserial/README.md
new file mode 100644
index 0000000..1cf4f5f
--- /dev/null
+++ b/.config/polybar/scripts/info-usbtoserial/README.md
@@ -0,0 +1,20 @@
+# Script: info-usbtoserial
+
+A small script which shows the USB-to-Serial converters that are connected.
+
+This script is able to display device changes in real time. For this udev is being used.
+
+
+## Configuration
+
+Copy `95-usbtoserial.rules` to `/etc/udev/rules.d/95-usbtoserial.rules`. Make sure that the paths in the file have been modified properly.
+
+
+## Module
+
+```ini
+[module/info-usbtoserial]
+type = custom/script
+exec = ~/polybar-scripts/info-usbtoserial.sh
+tail = true
+```
diff --git a/.config/polybar/scripts/info-usbtoserial/info-usbtoserial.sh b/.config/polybar/scripts/info-usbtoserial/info-usbtoserial.sh
new file mode 100644
index 0000000..a7b760d
--- /dev/null
+++ b/.config/polybar/scripts/info-usbtoserial/info-usbtoserial.sh
@@ -0,0 +1,44 @@
+#!/bin/sh
+usbtoserial_print() {
+ devices=$(find /dev/ -name "ttyUSB*")
+
+ counter=0
+ for device in $devices; do
+ device_name=$(udevadm info --query=property --export --name "$device" | grep ID_MODEL_FROM_DATABASE | cut -d "'" -f 2 | cut -d ' ' -f 1)
+
+ if [ $counter -gt 0 ]; then
+ printf ", %s" "$device_name"
+ else
+ printf "#1 %s" "$device_name"
+ fi
+
+ counter=$((counter + 1))
+ done
+
+ printf '\n'
+}
+
+path_pid="/tmp/polybar-usbtoserial.pid"
+
+case "$1" in
+ --update)
+ pid=$(cat $path_pid)
+
+ if [ "$pid" != "" ]; then
+ kill -10 "$pid"
+ fi
+ ;;
+ *)
+ echo $$ > $path_pid
+
+ trap exit INT
+ trap "echo" USR1
+
+ while true; do
+ usbtoserial_print
+
+ sleep 30 &
+ wait
+ done
+ ;;
+esac
diff --git a/.config/polybar/scripts/info-wakatime/README.md b/.config/polybar/scripts/info-wakatime/README.md
new file mode 100644
index 0000000..516fa7c
--- /dev/null
+++ b/.config/polybar/scripts/info-wakatime/README.md
@@ -0,0 +1,22 @@
+# Script: info-wakatime
+
+
+
+Display your daily coding time from wakatime.
+
+
+## Dependencies
+
+* `curl`
+* `jq`
+* obviously a wakatime.com account
+
+
+## Module
+
+```ini
+[module/info-wakatime]
+type = custom/script
+exec = ~/polybar-scripts/info-wakatime.sh
+interval = 60
+```
diff --git a/.config/polybar/scripts/info-wakatime/info-wakatime.sh b/.config/polybar/scripts/info-wakatime/info-wakatime.sh
new file mode 100644
index 0000000..25140ef
--- /dev/null
+++ b/.config/polybar/scripts/info-wakatime/info-wakatime.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+TOKEN=""
+
+wakatime_today="$(curl -sf --header "Authorization: Basic $(echo "$TOKEN" | base64)" https://wakatime.com/api/v1/users/current/status_bar/today | jq -r '.data.grand_total.text')"
+
+if [ -n "$wakatime_today" ]; then
+ echo "#1 $wakatime_today"
+else
+ echo "#2"
+fi
diff --git a/.config/polybar/scripts/info-wakatime/screenshots/1.png b/.config/polybar/scripts/info-wakatime/screenshots/1.png
new file mode 100644
index 0000000..8f6824b
Binary files /dev/null and b/.config/polybar/scripts/info-wakatime/screenshots/1.png differ
diff --git a/.config/polybar/scripts/info-wifinomadkronoplus/README.md b/.config/polybar/scripts/info-wifinomadkronoplus/README.md
new file mode 100644
index 0000000..99af5ba
--- /dev/null
+++ b/.config/polybar/scripts/info-wifinomadkronoplus/README.md
@@ -0,0 +1,20 @@
+# Script: info-nomadkronoplus
+
+When connected to the in-train Wi-Fi network of [Nomad Krono+ trains in the French Normandie](https://www.ter.sncf.com/normandie/services-contacts/services/krono-plus), this script shows the next stop, arrival time, and other information. The data is sourced from the local train information portal.
+Obviously, this script was hacked over the course of several train journeys. 🚄
+
+
+
+## Dependencies
+
+* `bc` (the [GNU basic calculator](https://www.gnu.org/software/bc/)), `jq`, and `curl` need to be in `$PATH`
+* You have to be logged in to the local SSID `NormandieTrainConnecte`.
+
+## Module
+
+```ini
+[module/info-nomadkronoplus]
+type = custom/script
+exec = ~/polybar-scripts/info-nomadkronoplus.sh
+interval = 10
+```
diff --git a/.config/polybar/scripts/info-wifinomadkronoplus/info-wifinomadkronoplus.sh b/.config/polybar/scripts/info-wifinomadkronoplus/info-wifinomadkronoplus.sh
new file mode 100644
index 0000000..f9bfb8f
--- /dev/null
+++ b/.config/polybar/scripts/info-wifinomadkronoplus/info-wifinomadkronoplus.sh
@@ -0,0 +1,58 @@
+#!/bin/sh
+
+icon="#"
+
+current_wifi=$(iwgetid -r)
+if [ "$current_wifi" = "NormandieTrainConnecte" ]; then
+ # Obtain route info. Bail out if it cannot be obtained or if the response
+ # is not valid JSON (based on jq's exit code).
+ if ! { circulation=$(curl --silent --fail https://wifi.normandie.fr/router/api/train/circulation); } then
+ echo "$icon In-train portal unreachable"
+ exit 0
+ fi
+ if ! { echo "$circulation" | jq --exit-status > /dev/null 2>&1; } then
+ echo "$icon In-train portal unreachable"
+ exit 0
+ fi
+
+ # In the list of stops on the current route, future stops are those which
+ # have an "arrival" key (the first station only has "departure"), and which
+ # either have a "progress" key showing 0% progress or which lack the
+ # "progress" key entirely. Stops are ordered according to the itinerary, so
+ # pick the first matching one to obtain the immediate next station.
+ station=$(echo "$circulation" | jq '[.stopList.stops[] |
+ select(
+ .arrival and (has("progress") | not) or .progress.progressPercentage == 0
+ )][0]')
+
+ # get name and track (as soon as it's available)
+ station_name=$(echo "$station" | jq -r '.location.name')
+ station_track=$(echo "$station" | jq -r '.track.number?')
+ if [ "$station_track" != "null" ]; then
+ station_name="$station_name, V. $station_track"
+ fi
+
+ # compute current delay in minutes based on "date" and "realDate"
+ scheduled_arrival=$(echo "$station" | jq -r '.arrival.date')
+ actual_arrival=$(echo "$station" | jq -r '.arrival.realDate')
+ delay_minutes="($(date +%s -d "$actual_arrival")-$(date +%s -d "$scheduled_arrival"))/60"
+ delay_minutes=$(echo "$delay_minutes" | bc)
+
+ # pretty-print arrival and delay
+ scheduled_arrival_pretty=$(date --date="$scheduled_arrival" +%H:%M)
+ delay_pretty=""
+ if [ "$delay_minutes" -ne 0 ]; then
+ delay_pretty=" %{F#d60606}(+$delay_minutes)%{F-}"
+ fi
+
+ gps=$(curl --silent --fail https://wifi.normandie.fr/router/api/train/gps)
+
+ # convert train speed from m/s to km/h
+ speed_mps=$(echo "$gps" | jq .speed)
+ speed_kph=$(echo "scale=0; $speed_mps * 3.6" | bc)
+ speed_kph_pretty="${speed_kph%.*} kph"
+
+ echo "$icon $scheduled_arrival_pretty$delay_pretty - $station_name - $speed_kph_pretty"
+else
+ echo ""
+fi
diff --git a/.config/polybar/scripts/info-wifinomadkronoplus/screenshots/1.png b/.config/polybar/scripts/info-wifinomadkronoplus/screenshots/1.png
new file mode 100644
index 0000000..371fc03
Binary files /dev/null and b/.config/polybar/scripts/info-wifinomadkronoplus/screenshots/1.png differ
diff --git a/.config/polybar/scripts/info-wifionice/README.md b/.config/polybar/scripts/info-wifionice/README.md
new file mode 100644
index 0000000..b3c38d3
--- /dev/null
+++ b/.config/polybar/scripts/info-wifionice/README.md
@@ -0,0 +1,19 @@
+# Script: info-wifionice
+
+This script shows some information about the current ICE train of Deutsche Bahn. It requests the data from the local information portal and was obviously hacked in a train.
+
+
+
+## Dependencies
+
+* `jq`, and `curl` need to be in `$PATH`
+* You have to be logged in to the local SSID `WIFIonICE`, see https://www.bahn.de/service/zug/wlan-im-zug.
+
+## Module
+
+```ini
+[module/info-wifionice]
+type = custom/script
+exec = ~/polybar-scripts/info-wifionice.sh
+interval = 10
+```
diff --git a/.config/polybar/scripts/info-wifionice/info-wifionice.sh b/.config/polybar/scripts/info-wifionice/info-wifionice.sh
new file mode 100644
index 0000000..4815847
--- /dev/null
+++ b/.config/polybar/scripts/info-wifionice/info-wifionice.sh
@@ -0,0 +1,46 @@
+#!/bin/sh
+
+icon="#"
+
+current_wifi=$(iwgetid -r)
+if { [ "$current_wifi" = "WIFIonICE" ] || [ "$current_wifi" = "WIFI@DB" ]; }; then
+ # Obtain route info. Bail out if it cannot be obtained or if the response
+ # is not valid JSON (based on jq's exit code).
+ if ! { wifionice=$(curl -sf https://iceportal.de/api1/rs/status); } then
+ echo "$icon In-train portal unreachable"
+ exit 0
+ fi
+ if ! { echo "$wifionice" | jq --exit-status > /dev/null 2>&1; } then
+ echo "$icon In-train portal unreachable"
+ exit 0
+ fi
+
+ if [ "$(echo "$wifionice" | jq .connection)" = "true" ]; then
+ wifionice_speed=$(echo "$wifionice" | jq .speed)
+ if [ "$wifionice_speed" -ne 0 ]; then
+ wifionice_speed=" - $wifionice_speed km/h"
+ else
+ wifionice_speed=""
+ fi
+
+ station=$(curl -sf https://iceportal.de/api1/rs/tripInfo/trip | jq '[.[].stops[]? | select(.info.passed == false)][0]')
+
+ station_name=$(echo "$station" | jq -r '.station.name')
+
+ station_track=$(echo "$station" | jq -r '.track.actual')
+
+ station_arrival=$(echo "$station" | jq -r '.timetable.scheduledArrivalTime')
+ station_arrival=$(date --date="@$((station_arrival / 1000))" +%H:%M)
+
+ station_delay=$(echo "$station" | jq -r '.timetable.arrivalDelay')
+ if [ -n "$station_delay" ]; then
+ station_delay=" %{F#d60606}($station_delay)%{F-}"
+ else
+ station_delay=""
+ fi
+
+ echo "$icon $station_arrival$station_delay - $station_name, Gl. $station_track$wifionice_speed"
+ fi
+else
+ echo ""
+fi
diff --git a/.config/polybar/scripts/info-wifionice/screenshots/1.png b/.config/polybar/scripts/info-wifionice/screenshots/1.png
new file mode 100644
index 0000000..b27617b
Binary files /dev/null and b/.config/polybar/scripts/info-wifionice/screenshots/1.png differ
diff --git a/.config/polybar/scripts/info-wmname/README.md b/.config/polybar/scripts/info-wmname/README.md
new file mode 100644
index 0000000..6d301b2
--- /dev/null
+++ b/.config/polybar/scripts/info-wmname/README.md
@@ -0,0 +1,21 @@
+# Script: info-wmname
+
+This script prints the value of the window manager name property of the root window.
+
+The BSPWM window manger, and maybe some more, has some problems with java scaling. To solve this you can [set the value of the window manager name property](https://wiki.archlinux.org/index.php/java#Impersonate_another_window_manager) to something different.
+
+
+## Dependencies
+
+* `wmname`
+
+
+## Module
+
+```ini
+[module/info-wmname]
+type = custom/script
+exec = ~/polybar-scripts/info-wmname.sh
+interval = 5
+click-left = ~/polybar-scripts/info-wmname.sh --toggle &
+```
diff --git a/.config/polybar/scripts/info-wmname/info-wmname.sh b/.config/polybar/scripts/info-wmname/info-wmname.sh
new file mode 100644
index 0000000..4a75838
--- /dev/null
+++ b/.config/polybar/scripts/info-wmname/info-wmname.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+case "$1" in
+ --toggle)
+ if [ "$(wmname)" != "BSPWM" ]; then
+ wmname BSPWM
+ else
+ wmname LG3D
+ fi
+ ;;
+ *)
+ echo "# $(wmname)"
+ ;;
+esac
diff --git a/.config/polybar/scripts/info-xampp/README.md b/.config/polybar/scripts/info-xampp/README.md
new file mode 100644
index 0000000..0269fa4
--- /dev/null
+++ b/.config/polybar/scripts/info-xampp/README.md
@@ -0,0 +1,24 @@
+# Script: info-xampp
+
+The Script prints the status of [XAMPP](https://www.apachefriends.org/de/index.html) services (Apache, MySQL, ProFTPD) if they are running.
+
+
+
+
+## Configuration
+
+You have to add the `xampp` command to the `/etc/sudoers` NOPASSWD of your user:
+
+```ini
+user ALL=(ALL) NOPASSWD: /opt/lampp/xampp
+```
+
+
+## Module
+
+```ini
+[module/info-xampp]
+type = custom/script
+exec = ~/polybar-scripts/info-xampp.sh
+interval = 10
+```
diff --git a/.config/polybar/scripts/info-xampp/info-xampp.sh b/.config/polybar/scripts/info-xampp/info-xampp.sh
new file mode 100644
index 0000000..91f0ee5
--- /dev/null
+++ b/.config/polybar/scripts/info-xampp/info-xampp.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+if sudo /opt/lampp/xampp status | grep -q "Apache is running."; then
+ status_apache="#11"
+else
+ status_apache="#12"
+fi
+
+if sudo /opt/lampp/xampp status | grep -q "MySQL is running."; then
+ status_mysql="#21"
+else
+ status_mysql="#22"
+fi
+
+if sudo /opt/lampp/xampp status | grep -q "ProFTPD is running."; then
+ status_ftp="#31"
+else
+ status_ftp="#32"
+fi
+
+echo "$status_apache $status_mysql $status_ftp"
diff --git a/.config/polybar/scripts/info-xampp/screenshots/1.png b/.config/polybar/scripts/info-xampp/screenshots/1.png
new file mode 100644
index 0000000..f8598b7
Binary files /dev/null and b/.config/polybar/scripts/info-xampp/screenshots/1.png differ
diff --git a/.config/polybar/scripts/isrunning-claudius/README.md b/.config/polybar/scripts/isrunning-claudius/README.md
new file mode 100644
index 0000000..dd2a269
--- /dev/null
+++ b/.config/polybar/scripts/isrunning-claudius/README.md
@@ -0,0 +1,16 @@
+# Script: isrunning-claudius
+
+A tiny module to report the state of claudius, the alternative filepicker for Discord.
+
+Left click launches or closes claudius.
+
+
+## Module
+
+```ini
+[module/isrunning-claudius]
+type = custom/script
+exec = ~/polybar-scripts/isrunning-claudius.sh
+interval = 5
+click-left = ~/polybar-scripts/isrunning-claudius --toggle &
+```
diff --git a/.config/polybar/scripts/isrunning-claudius/isrunning-claudius.sh b/.config/polybar/scripts/isrunning-claudius/isrunning-claudius.sh
new file mode 100644
index 0000000..8cacaaf
--- /dev/null
+++ b/.config/polybar/scripts/isrunning-claudius/isrunning-claudius.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+case "$1" in
+ --toggle)
+ if [ "$(pgrep claudius)" ]; then
+ pkill claudius
+ else
+ claudius &
+ fi
+ ;;
+ *)
+ if [ "$(pgrep claudius)" ]; then
+ echo "#1"
+ else
+ echo "#2"
+ fi
+ ;;
+esac
diff --git a/.config/polybar/scripts/isrunning-compton/README.md b/.config/polybar/scripts/isrunning-compton/README.md
new file mode 100644
index 0000000..ebe9db7
--- /dev/null
+++ b/.config/polybar/scripts/isrunning-compton/README.md
@@ -0,0 +1,14 @@
+# Script: isrunning-compton
+
+A simple script that allows you to toggle compton and shows if it is running.
+
+
+## Module
+
+```ini
+[module/isrunning-compton]
+type = custom/script
+exec = ~/polybar-scripts/isrunning-compton.sh
+interval = 5
+click-left = ~/polybar-scripts/isrunning-compton.sh --toggle &
+```
diff --git a/.config/polybar/scripts/isrunning-compton/isrunning-compton.sh b/.config/polybar/scripts/isrunning-compton/isrunning-compton.sh
new file mode 100644
index 0000000..c94b265
--- /dev/null
+++ b/.config/polybar/scripts/isrunning-compton/isrunning-compton.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+case "$1" in
+ --toggle)
+ if [ "$(pgrep -x compton)" ]; then
+ pkill compton
+ else
+ compton -b --config ~/.config/compton/config
+ fi
+ ;;
+ *)
+ if [ "$(pgrep -x compton)" ]; then
+ echo "#1"
+ else
+ echo "#2"
+ fi
+ ;;
+esac
diff --git a/.config/polybar/scripts/isrunning-dropbox/README.md b/.config/polybar/scripts/isrunning-dropbox/README.md
new file mode 100644
index 0000000..c3ec7b2
--- /dev/null
+++ b/.config/polybar/scripts/isrunning-dropbox/README.md
@@ -0,0 +1,14 @@
+# Script: isrunning-dropbox
+
+A script that shows if the dropbox client is running. You can also start and stop the client.
+
+
+## Module
+
+```ini
+[module/isrunning-dropbox]
+type = custom/script
+exec = ~/polybar-scripts/isrunning-dropbox.sh
+interval = 5
+click-left = ~/polybar-scripts/isrunning-dropbox.sh --toggle &
+```
diff --git a/.config/polybar/scripts/isrunning-dropbox/isrunning-dropbox.sh b/.config/polybar/scripts/isrunning-dropbox/isrunning-dropbox.sh
new file mode 100644
index 0000000..bc4a398
--- /dev/null
+++ b/.config/polybar/scripts/isrunning-dropbox/isrunning-dropbox.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+case "$1" in
+ --toggle)
+ if [ "$(pgrep dropbox)" ]; then
+ pkill -f dropbox
+ else
+ dropbox &
+ fi
+ ;;
+ *)
+ if [ "$(pgrep dropbox)" ]; then
+ echo "#1"
+ else
+ echo "#2"
+ fi
+ ;;
+esac
diff --git a/.config/polybar/scripts/isrunning-noisetorch/README.md b/.config/polybar/scripts/isrunning-noisetorch/README.md
new file mode 100644
index 0000000..eb9fa54
--- /dev/null
+++ b/.config/polybar/scripts/isrunning-noisetorch/README.md
@@ -0,0 +1,20 @@
+# Script: isrunning-noisetorch
+
+A script that outputs an icon if noisetorch is loaded as a pulseaudio module.
+
+
+
+
+## Dependencies
+
+* [NoiseTorch](https://github.com/lawl/NoiseTorch)
+
+
+## Module
+
+```ini
+[module/isrunning-noisetorch]
+type = custom/script
+exec = ~/.config/polybar/modules/isrunning-noisetorch.sh
+interval = 20
+```
diff --git a/.config/polybar/scripts/isrunning-noisetorch/isrunning-noisetorch.sh b/.config/polybar/scripts/isrunning-noisetorch/isrunning-noisetorch.sh
new file mode 100644
index 0000000..c4ba6e1
--- /dev/null
+++ b/.config/polybar/scripts/isrunning-noisetorch/isrunning-noisetorch.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+nmodules="$(pactl list modules short | grep -c noisetorch)"
+[ "$nmodules" = 0 ] && echo "" || echo ""
+
diff --git a/.config/polybar/scripts/isrunning-noisetorch/screenshots/1.png b/.config/polybar/scripts/isrunning-noisetorch/screenshots/1.png
new file mode 100644
index 0000000..9b70b9d
Binary files /dev/null and b/.config/polybar/scripts/isrunning-noisetorch/screenshots/1.png differ
diff --git a/.config/polybar/scripts/isrunning-offlineimap/README.md b/.config/polybar/scripts/isrunning-offlineimap/README.md
new file mode 100644
index 0000000..bc01bf9
--- /dev/null
+++ b/.config/polybar/scripts/isrunning-offlineimap/README.md
@@ -0,0 +1,14 @@
+# Script: isrunning-offlineimap
+
+A script that shows if offlineimap is running. The scripts require you to have setup offlineimap yourself.
+
+
+## Module
+
+```ini
+[module/offlineimap-isrunning]
+type = custom/script
+exec = ~/polybar-scripts/offlineimap-isrunning.sh
+interval = 5
+click-left = ~/polybar-scripts/offlineimap-isrunning.sh --toggle &
+```
diff --git a/.config/polybar/scripts/isrunning-offlineimap/isrunning-offlineimap.sh b/.config/polybar/scripts/isrunning-offlineimap/isrunning-offlineimap.sh
new file mode 100644
index 0000000..1202663
--- /dev/null
+++ b/.config/polybar/scripts/isrunning-offlineimap/isrunning-offlineimap.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+case "$1" in
+ --toggle)
+ if [ "$(pgrep offlineimap)" ]; then
+ pkill -f offlineimap
+ else
+ nohup offlineimap > /tmp/offlineimap.log &
+ fi
+ ;;
+ *)
+ if [ "$(pgrep offlineimap)" ]; then
+ echo "#1 Online"
+ else
+ echo "#2 Offline"
+ fi
+ ;;
+esac
diff --git a/.config/polybar/scripts/isrunning-service/README.md b/.config/polybar/scripts/isrunning-service/README.md
new file mode 100644
index 0000000..97ec010
--- /dev/null
+++ b/.config/polybar/scripts/isrunning-service/README.md
@@ -0,0 +1,18 @@
+# Script: isrunning-service
+
+A script that shows if a systemd service is running. It uses `journalctl` to get realtime output.
+
+
+## Configuration
+
+Make sure that your user is member of the group `systemd-journal` to read all events.
+
+
+## Module
+
+```ini
+[module/isrunning-service]
+type = custom/script
+exec = ~/polybar-scripts/isrunning-service.sh
+tail = true
+```
diff --git a/.config/polybar/scripts/isrunning-service/isrunning-service.sh b/.config/polybar/scripts/isrunning-service/isrunning-service.sh
new file mode 100644
index 0000000..fbab122
--- /dev/null
+++ b/.config/polybar/scripts/isrunning-service/isrunning-service.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+UNIT="docker.service"
+
+journalctl --follow -o cat --unit $UNIT | while read -r; do
+ if [ "$(systemctl is-active "$UNIT")" = "active" ]; then
+ echo "#1"
+ else
+ echo "#2"
+ fi
+done
diff --git a/.config/polybar/scripts/network-huawei-modem/README.md b/.config/polybar/scripts/network-huawei-modem/README.md
new file mode 100644
index 0000000..e358552
--- /dev/null
+++ b/.config/polybar/scripts/network-huawei-modem/README.md
@@ -0,0 +1,27 @@
+# Script: network-huawei-modem
+
+Print stats from Huawei modem sticks. Such as signal levels, sms count and traffic bandwidth.
+
+Tested with E3372h-320, but should work with others.
+
+
+
+
+## Dependencies
+
+* [`Salamek/huawei-lte-api`](https://github.com/Salamek/huawei-lte-api)
+
+
+## Configuration
+
+Just insert your modem ip and credentials into heading of script.
+
+
+## Module
+
+```ini
+[module/network-huawei-modem]
+type = custom/script
+exec = ~/polybar-scripts/network-huawei-modem.py
+interval = 5
+```
diff --git a/.config/polybar/scripts/network-huawei-modem/network-huawei-modem.py b/.config/polybar/scripts/network-huawei-modem/network-huawei-modem.py
new file mode 100755
index 0000000..c0045ef
--- /dev/null
+++ b/.config/polybar/scripts/network-huawei-modem/network-huawei-modem.py
@@ -0,0 +1,45 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*- # PEP 263
+
+from huawei_lte_api.Client import Client
+from huawei_lte_api.Connection import Connection
+
+# Configuration
+host = '192.168.8.1'
+username = 'admin'
+password = ''
+
+MODEM_URL = f"http://{username}:{password}@{host}/"
+
+
+def scale_units(rate):
+ decimal_places = 2
+ for unit in ['bps', 'Kbps', 'Mbps', 'Gbps', 'Tbps']:
+ if rate < 1000.0:
+ if unit == 'bps':
+ decimal_places = 0
+ break
+ rate /= 1000.0
+ return f"{rate:.{decimal_places}f}{unit}"
+
+
+if __name__ == '__main__':
+ with Connection(MODEM_URL) as connection:
+ # This just simplifies access to separate API groups,
+ # you can use device = Device(connection) if you want
+ client = Client(connection)
+
+ signal = client.device.signal()
+ traffic = client.monitoring.traffic_statistics()
+ sms = client.sms.sms_count()
+ status = client.monitoring.status()
+ sms_unread = int(sms['LocalUnread'])
+
+ power = status['SignalIcon']
+ sinr = signal['sinr']
+ sms_icon = '' if sms_unread else ''
+ down = scale_units(int(traffic['CurrentDownloadRate']) * 8)
+ up = scale_units(int(traffic['CurrentUploadRate']) * 8)
+ result = f":{power} SINR:{sinr} {sms_icon}:{sms_unread} {down} {up}"
+
+ print(result)
diff --git a/.config/polybar/scripts/network-huawei-modem/screenshots/1.png b/.config/polybar/scripts/network-huawei-modem/screenshots/1.png
new file mode 100644
index 0000000..4842a25
Binary files /dev/null and b/.config/polybar/scripts/network-huawei-modem/screenshots/1.png differ
diff --git a/.config/polybar/scripts/network-ipinfo.io/README.md b/.config/polybar/scripts/network-ipinfo.io/README.md
new file mode 100644
index 0000000..5150c90
--- /dev/null
+++ b/.config/polybar/scripts/network-ipinfo.io/README.md
@@ -0,0 +1,26 @@
+# Script: network-ipinfo.io
+
+Shows your public IP address and country of origin retrieved from `ipinfo.io`.
+
+
+
+
+## Dependencies
+
+* `curl`
+* `jq`
+
+
+## Configuration
+
+The minimum interval of 60 seconds is important since free usage is limited to 50,000 API requests per month.
+
+
+## Module
+
+```ini
+[module/network-ipinfo.io]
+type = custom/script
+exec = ~/.config/polybar/network-ipinfo.io.sh
+interval = 60
+```
diff --git a/.config/polybar/scripts/network-ipinfo.io/network-ipinfo.io.sh b/.config/polybar/scripts/network-ipinfo.io/network-ipinfo.io.sh
new file mode 100644
index 0000000..24c53ea
--- /dev/null
+++ b/.config/polybar/scripts/network-ipinfo.io/network-ipinfo.io.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+ipinfo=$(curl -sf "https://ipinfo.io/json")
+
+if [ -n "$ipinfo" ]; then
+ ipinfo_ip=$(echo "$ipinfo" | jq -r '.ip')
+ ipinfo_country=$(echo "$ipinfo" | jq -r '.country')
+
+ echo "# $ipinfo_ip [ $ipinfo_country ]"
+else
+ echo ""
+fi
diff --git a/.config/polybar/scripts/network-ipinfo.io/screenshots/1.png b/.config/polybar/scripts/network-ipinfo.io/screenshots/1.png
new file mode 100644
index 0000000..58f99da
Binary files /dev/null and b/.config/polybar/scripts/network-ipinfo.io/screenshots/1.png differ
diff --git a/.config/polybar/scripts/network-localip/README.md b/.config/polybar/scripts/network-localip/README.md
new file mode 100644
index 0000000..dd04561
--- /dev/null
+++ b/.config/polybar/scripts/network-localip/README.md
@@ -0,0 +1,15 @@
+# Script: network-localip
+
+This script shows the local IP of the current connection.
+
+
+
+
+## Module
+
+```ini
+[module/network-localip]
+type = custom/script
+exec = ~/polybar-scripts/network-localip.sh
+interval = 60
+```
diff --git a/.config/polybar/scripts/network-localip/network-localip.sh b/.config/polybar/scripts/network-localip/network-localip.sh
new file mode 100644
index 0000000..bf42815
--- /dev/null
+++ b/.config/polybar/scripts/network-localip/network-localip.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+local_interface=$(route | awk '/^default/{print $NF}')
+local_ip=$(ip addr show "$local_interface" | grep -w "inet" | awk '{ print $2; }' | sed 's/\/.*$//')
+
+echo "# $local_ip"
diff --git a/.config/polybar/scripts/network-localip/screenshots/1.png b/.config/polybar/scripts/network-localip/screenshots/1.png
new file mode 100644
index 0000000..bc7f374
Binary files /dev/null and b/.config/polybar/scripts/network-localip/screenshots/1.png differ
diff --git a/.config/polybar/scripts/network-networkmanager/README.md b/.config/polybar/scripts/network-networkmanager/README.md
new file mode 100644
index 0000000..13bcc19
--- /dev/null
+++ b/.config/polybar/scripts/network-networkmanager/README.md
@@ -0,0 +1,15 @@
+# Script: network-networkmanager
+
+A shell script that shows the status of NetworkManager.
+
+It shows connection changes in real time.
+
+
+## Module
+
+```ini
+[module/network-networkmanager]
+type = custom/script
+exec = ~/polybar-scripts/network-networkmanager.sh
+tail = true
+```
diff --git a/.config/polybar/scripts/network-networkmanager/network-networkmanager.sh b/.config/polybar/scripts/network-networkmanager/network-networkmanager.sh
new file mode 100644
index 0000000..31dbf3d
--- /dev/null
+++ b/.config/polybar/scripts/network-networkmanager/network-networkmanager.sh
@@ -0,0 +1,71 @@
+#!/bin/sh
+
+network_print() {
+ connection_list=$(nmcli -t -f name,type,device,state connection show --order name --active 2>/dev/null | grep -v ':bridge:\|:lo:')
+ counter=0
+
+ if [ -n "$connection_list" ] && [ "$(echo "$connection_list" | wc -l)" -gt 0 ]; then
+ echo "$connection_list" | while read -r line; do
+ description=$(echo "$line" | sed -e 's/\\:/-/g' | cut -d ':' -f 1)
+ type=$(echo "$line" | sed -e 's/\\:/-/g' | cut -d ':' -f 2)
+ device=$(echo "$line" | sed -e 's/\\:/-/g' | cut -d ':' -f 3)
+ state=$(echo "$line" | sed -e 's/\\:/-/g' | cut -d ':' -f 4)
+
+ if [ "$state" = "activated" ]; then
+ if [ "$type" = "802-11-wireless" ]; then
+ icon="#1"
+
+ signal=$(nmcli -t -f in-use,signal device wifi list ifname "$device" | grep "\*" | cut -d ':' -f 2)
+ if [ "$signal" -lt 40 ]; then
+ description="$description - %{F#f9cc18}$signal%%{F-}"
+ fi
+ elif [ "$type" = "802-3-ethernet" ]; then
+ icon="#2"
+
+ speed="$(cat /sys/class/net/"$device"/speed)"
+ if [ "$speed" -ne -1 ]; then
+ if [ "$speed" -eq 1000 ]; then
+ speed="1G"
+ else
+ speed=$speed"M"
+ fi
+ else
+ speed="?"
+ fi
+
+ description="$description ($speed)"
+ elif [ "$type" = "bluetooth" ]; then
+ icon="#3"
+ fi
+ elif [ "$state" = "activating" ]; then
+ icon="#4"
+ elif [ "$state" = "deactivating" ]; then
+ icon="#5"
+ fi
+
+ if [ $counter -gt 0 ]; then
+ printf " %s %s" "$icon" "$description"
+ else
+ printf "%s %s" "$icon" "$description"
+ fi
+
+ counter=$((counter + 1))
+ done
+
+ printf "\n"
+ else
+ echo "#6"
+ fi
+}
+
+trap exit INT
+
+while true; do
+ network_print
+
+ timeout 60s nmcli monitor | while read -r REPLY; do
+ network_print
+ done &
+
+ wait
+done
diff --git a/.config/polybar/scripts/network-openwrt-status/README.md b/.config/polybar/scripts/network-openwrt-status/README.md
new file mode 100644
index 0000000..094705e
--- /dev/null
+++ b/.config/polybar/scripts/network-openwrt-status/README.md
@@ -0,0 +1,27 @@
+# Script: network-openwrt-status
+
+Print stats from OpenWrt router. Such as signal levels, sms count and traffic bandwidth.
+
+Written for Microdrive Tandem-4GT-OEM modem, but can be adopted to work with all OpenWrt routers.
+
+
+
+
+## Dependencies
+
+* `python-requests`
+
+
+## Configuration
+
+Just insert your router ip and credentials into heading of script.
+
+
+## Module
+
+```ini
+[module/network-openwrt-status]
+type = custom/script
+exec = ~/polybar-scripts/network-openwrt-status.py
+interval = 5
+```
diff --git a/.config/polybar/scripts/network-openwrt-status/network-openwrt-status.py b/.config/polybar/scripts/network-openwrt-status/network-openwrt-status.py
new file mode 100755
index 0000000..83a1594
--- /dev/null
+++ b/.config/polybar/scripts/network-openwrt-status/network-openwrt-status.py
@@ -0,0 +1,112 @@
+#!/usr/bin/python3
+# -*- coding: utf-8 -*- # PEP 263
+
+import requests
+from binascii import unhexlify
+
+# Configuration
+host = '192.168.8.1'
+username = 'root'
+password = ''
+
+LOGIN_URL = f"http://{host}/cgi-bin/luci/"
+MODEM_URL = f"http://{host}/cgi-bin/luci/?status=1"
+SMS_URL = f"http://{host}/cgi-bin/luci/admin/services/modem_read_sms/all?block=0"
+BW_URL = f"http://{host}/cgi-bin/luci/admin/status/realtime/bandwidth_status/wwan0"
+
+
+def scale_units(rate):
+ # input: integer
+ decimal_places = 2
+ for unit in ['bps', 'Kbps', 'Mbps', 'Gbps', 'Tbps']:
+ if rate < 1000.0:
+ if unit == 'bps':
+ decimal_places = 0
+ break
+ rate /= 1000.0
+ return f"{rate:.{decimal_places}f}{unit}"
+
+
+def sms_concatenate(data):
+ # input: list of dicts
+ sms = list()
+ concat = dict()
+ for item in data:
+ if not item['fail']:
+ if 'c_ref' in item:
+ if item['c_ref'] not in concat:
+ concat[item['c_ref']] = list()
+ concat[item['c_ref']].append(item)
+ else:
+ sms.append(item)
+ if len(concat):
+ for key, parts in concat.items():
+ parts.sort(key=lambda x: x['c_cur'])
+ for part in parts:
+ if part['c_cur'] == 1:
+ sms.append(part)
+ else:
+ sms[-1]['data'] += part['data']
+ return sms
+
+
+def sms_decode(sms):
+ # input: dict
+ if sms['dcs'] == 2:
+ sms['data'] = unhexlify(sms['data']).decode('utf-16be')
+ return sms
+
+
+if __name__ == '__main__':
+ # setup session and authenticate
+ s = requests.Session()
+ s.post(LOGIN_URL, data={'luci_username': username, 'luci_password': password})
+ s.headers.update({'Content-Type': 'application/json'})
+
+ # get lte modem stats (luci-mod-microdrive)
+ r = s.get(MODEM_URL)
+ r = r.json()
+ name = r['ifg']['spn']
+ lvl = r['ifg']['rssi_lv']
+ rssi = r['ifg']['cell_lte'][0]['rssi']
+ rsrp = r['ifg']['cell_lte'][0]['rsrp']
+ sinr = r['ifg']['cell_lte'][0]['sinr']
+ result = f"{name} {lvl}% RSSI {rssi}dBm RSRP {rsrp}dBm SINR {sinr}dB"
+
+ # get sms count (luci-mod-microdrive)
+ r = s.get(SMS_URL)
+ r = r.json()
+ mem_total = 255
+ mem_used = 0
+ sms_count = 0
+ if r['code'] == 0 and 'out' in r and 'sms' in r['out']:
+ mem_total = r['out']['mem']['total']
+ mem_used = r['out']['mem']['used']
+ data = r['out']['sms']
+ if len(data):
+ sms = sms_concatenate(data)
+ sms_count = len(sms)
+ icon = '' if sms_count else ''
+ # if mem_used > mem_total * 0.90:
+ # sms_count = 'MANY'
+ result = result + f" {icon} {sms_count}"
+
+ # get traffic stats
+ # the response is array of array [[TIME, RXB, RXP, TXB, TXP]]
+ # we only need two last items with TIME, RXB and TXB fields
+ r = s.get(BW_URL)
+ r = r.json()
+ rxb = 0
+ txb = 0
+ if len(r) >= 2:
+ # get last two items
+ a = r.pop()
+ b = r.pop()
+ # normalize difference against time interval
+ # this code from luci XHR.poll function
+ time_delta = a[0] - b[0]
+ rxb = scale_units((a[1] - b[1]) / time_delta * 8)
+ txb = scale_units((a[3] - b[3]) / time_delta * 8)
+ result = result + f" {rxb} {txb}"
+
+ print(result)
diff --git a/.config/polybar/scripts/network-openwrt-status/screenshots/1.png b/.config/polybar/scripts/network-openwrt-status/screenshots/1.png
new file mode 100644
index 0000000..ebaa55c
Binary files /dev/null and b/.config/polybar/scripts/network-openwrt-status/screenshots/1.png differ
diff --git a/.config/polybar/scripts/network-publicip/README.md b/.config/polybar/scripts/network-publicip/README.md
new file mode 100644
index 0000000..7282ce2
--- /dev/null
+++ b/.config/polybar/scripts/network-publicip/README.md
@@ -0,0 +1,20 @@
+# Script: network-publicip
+
+This script shows the public IP of the current connection.
+
+
+
+
+## Dependencies
+
+* `curl`
+
+
+## Module
+
+```ini
+[module/network-publicip]
+type = custom/script
+exec = ~/polybar-scripts/network-publicip.sh
+interval = 60
+```
diff --git a/.config/polybar/scripts/network-publicip/network-publicip.sh b/.config/polybar/scripts/network-publicip/network-publicip.sh
new file mode 100644
index 0000000..2349ab3
--- /dev/null
+++ b/.config/polybar/scripts/network-publicip/network-publicip.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+echo "# $(curl -4 -sf ifconfig.co)"
diff --git a/.config/polybar/scripts/network-publicip/screenshots/1.png b/.config/polybar/scripts/network-publicip/screenshots/1.png
new file mode 100644
index 0000000..2eac747
Binary files /dev/null and b/.config/polybar/scripts/network-publicip/screenshots/1.png differ
diff --git a/.config/polybar/scripts/network-traffic/README.md b/.config/polybar/scripts/network-traffic/README.md
new file mode 100644
index 0000000..1482d83
--- /dev/null
+++ b/.config/polybar/scripts/network-traffic/README.md
@@ -0,0 +1,25 @@
+# Script: network-traffic
+
+A script that displays the current network traffic.
+
+It allows you to count traffic from more then one interface.
+
+
+## Dependencies
+
+* `bc`
+
+
+## Configuration
+
+Change the values in `INTERVAL` and `INTERFACES`. You can also choose between bit and byte output.
+
+
+## Module
+
+```ini
+[module/network-traffic]
+type = custom/script
+exec = ~/polybar-scripts/network-traffic.sh
+tail = true
+```
diff --git a/.config/polybar/scripts/network-traffic/network-traffic.sh b/.config/polybar/scripts/network-traffic/network-traffic.sh
new file mode 100644
index 0000000..a08d8fb
--- /dev/null
+++ b/.config/polybar/scripts/network-traffic/network-traffic.sh
@@ -0,0 +1,61 @@
+#!/bin/bash
+
+print_bytes() {
+ if [ "$1" -eq 0 ] || [ "$1" -lt 1000 ]; then
+ bytes="0 kB/s"
+ elif [ "$1" -lt 1000000 ]; then
+ bytes="$(echo "$1/1000" | bc -l | LANG=C xargs printf "%.f\n") kB/s"
+ else
+ bytes="$(echo "$1/1000000" | bc -l | LANG=C xargs printf "%.1f\n") MB/s"
+ fi
+
+ echo "$bytes"
+}
+
+print_bit() {
+ if [ "$1" -eq 0 ] || [ "$1" -lt 10 ]; then
+ bit="0 B"
+ elif [ "$1" -lt 100 ]; then
+ bit="$(echo "$1*8" | bc -l | LANG=C xargs printf "%.f\n") B"
+ elif [ "$1" -lt 100000 ]; then
+ bit="$(echo "$1*8/1000" | bc -l | LANG=C xargs printf "%.f\n") K"
+ else
+ bit="$(echo "$1*8/1000000" | bc -l | LANG=C xargs printf "%.1f\n") M"
+ fi
+
+ echo "$bit"
+}
+
+INTERVAL=10
+INTERFACES="enp0s25 wlp3s0"
+
+declare -A bytes
+
+for interface in $INTERFACES; do
+ bytes[past_rx_$interface]="$(cat /sys/class/net/"$interface"/statistics/rx_bytes)"
+ bytes[past_tx_$interface]="$(cat /sys/class/net/"$interface"/statistics/tx_bytes)"
+done
+
+while true; do
+ down=0
+ up=0
+
+ for interface in $INTERFACES; do
+ bytes[now_rx_$interface]="$(cat /sys/class/net/"$interface"/statistics/rx_bytes)"
+ bytes[now_tx_$interface]="$(cat /sys/class/net/"$interface"/statistics/tx_bytes)"
+
+ bytes_down=$(((${bytes[now_rx_$interface]} - ${bytes[past_rx_$interface]}) / INTERVAL))
+ bytes_up=$(((${bytes[now_tx_$interface]} - ${bytes[past_tx_$interface]}) / INTERVAL))
+
+ down=$(( "$down" + "$bytes_down" ))
+ up=$(( "$up" + "$bytes_up" ))
+
+ bytes[past_rx_$interface]=${bytes[now_rx_$interface]}
+ bytes[past_tx_$interface]=${bytes[now_tx_$interface]}
+ done
+
+ echo "Download: $(print_bytes $down) / Upload: $(print_bytes $up)"
+ # echo "Download: $(print_bit $down) / Upload: $(print_bit $up)"
+
+ sleep $INTERVAL
+done
diff --git a/.config/polybar/scripts/news-archlinux/README.md b/.config/polybar/scripts/news-archlinux/README.md
new file mode 100644
index 0000000..1bb28cb
--- /dev/null
+++ b/.config/polybar/scripts/news-archlinux/README.md
@@ -0,0 +1,18 @@
+# Script: news-archlinux
+
+A Python script that shows Arch Linux RSS news.
+
+
+## Dependencies
+
+* [python-feedparser](https://github.com/kurtmckee/feedparser//)
+
+
+## Module
+
+```ini
+[module/news-archlinux]
+type = custom/script
+exec = ~/polybar-scripts/news-archlinux.py
+interval = 600
+```
diff --git a/.config/polybar/scripts/news-archlinux/news-archlinux.py b/.config/polybar/scripts/news-archlinux/news-archlinux.py
new file mode 100644
index 0000000..e72fa8a
--- /dev/null
+++ b/.config/polybar/scripts/news-archlinux/news-archlinux.py
@@ -0,0 +1,7 @@
+#!/usr/bin/python
+from feedparser import parse
+
+URL = 'https://www.archlinux.org/feeds/news/'
+ENTRIES = 1
+
+[print(x.title) for x in parse(URL).entries[:ENTRIES]]
diff --git a/.config/polybar/scripts/notification-chess/README.md b/.config/polybar/scripts/notification-chess/README.md
new file mode 100644
index 0000000..899c1fe
--- /dev/null
+++ b/.config/polybar/scripts/notification-chess/README.md
@@ -0,0 +1,23 @@
+# Script: notification-chess
+
+A small script that indicates whether you need to move.
+
+
+
+
+## Dependencies
+
+* `curl`
+* `jq`
+* obviously a chess.com account
+
+
+## Module
+
+```ini
+[module/notification-chess]
+type = custom/script
+exec = ~/polybar-scripts/notification-chess.sh
+interval = 10
+click-left = xdg-open https://www.chess.com/goto_ready_game & disown
+```
diff --git a/.config/polybar/scripts/notification-chess/notification-chess.sh b/.config/polybar/scripts/notification-chess/notification-chess.sh
new file mode 100644
index 0000000..8bf3a34
--- /dev/null
+++ b/.config/polybar/scripts/notification-chess/notification-chess.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+USERNAME=""
+games=$(curl -sf "https://api.chess.com/pub/player/$USERNAME/games/to-move" | jq ".[] | length")
+
+if [ "$games" -gt 0 ]; then
+ echo "#1 $games"
+else
+ echo "#2"
+fi
diff --git a/.config/polybar/scripts/notification-chess/screenshots/1.png b/.config/polybar/scripts/notification-chess/screenshots/1.png
new file mode 100644
index 0000000..0d80046
Binary files /dev/null and b/.config/polybar/scripts/notification-chess/screenshots/1.png differ
diff --git a/.config/polybar/scripts/notification-github/README.md b/.config/polybar/scripts/notification-github/README.md
new file mode 100644
index 0000000..6d3b0e6
--- /dev/null
+++ b/.config/polybar/scripts/notification-github/README.md
@@ -0,0 +1,24 @@
+# Script: notification-github
+
+A small script that shows your GitHub notifications.
+
+
+## Dependencies
+
+* `curl`
+* `jq`
+
+
+## Configuration
+
+Generate a token at `GitHub Settings` > `Developer settings` > `Personal access tokens`.
+
+
+## Module
+
+```ini
+[module/notification-github]
+type = custom/script
+exec = ~/polybar-scripts/notification-github.sh
+interval = 60
+```
diff --git a/.config/polybar/scripts/notification-github/notification-github.sh b/.config/polybar/scripts/notification-github/notification-github.sh
new file mode 100644
index 0000000..7626c13
--- /dev/null
+++ b/.config/polybar/scripts/notification-github/notification-github.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+USER=""
+TOKEN="1234567890"
+
+notifications=$(echo "user = \"$USER:$TOKEN\"" | curl -sf -K- https://api.github.com/notifications | jq ".[].unread" | grep -c true)
+
+if [ "$notifications" -gt 0 ]; then
+ echo "# $notifications"
+else
+ echo ""
+fi
diff --git a/.config/polybar/scripts/notification-mattermost/README.md b/.config/polybar/scripts/notification-mattermost/README.md
new file mode 100644
index 0000000..b08cd2a
--- /dev/null
+++ b/.config/polybar/scripts/notification-mattermost/README.md
@@ -0,0 +1,24 @@
+# Script: notification-mattermost
+
+A small script that shows your unread Mattermost messages and mentions.
+
+
+## Dependencies
+
+* `curl`
+* `jq`
+
+
+## Configuration
+
+Generate a token at `Account Settings` > `Security` > `Personal Access Tokens`. You have to enable tokens in your server config.
+
+
+## Module
+
+```ini
+[module/notification-mattermost]
+type = custom/script
+exec = ~/polybar-scripts/notification-mattermost.sh
+interval = 60
+```
diff --git a/.config/polybar/scripts/notification-mattermost/notification-mattermost.sh b/.config/polybar/scripts/notification-mattermost/notification-mattermost.sh
new file mode 100644
index 0000000..528182d
--- /dev/null
+++ b/.config/polybar/scripts/notification-mattermost/notification-mattermost.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+MATTERMOST_SERVER="https://mattermost-server.net"
+MATTERMOST_TOKEN=""
+
+if notifications=$(curl -sf -H "Authorization: Bearer $MATTERMOST_TOKEN" "$MATTERMOST_SERVER/api/v4/users/me/teams/unread"); then
+ notifications_msg=$(echo "$notifications" | jq -s 'map(.[].msg_count) | add')
+ notifications_mention=$(echo "$notifications" | jq -s 'map(.[].mention_count) | add')
+
+ if [ "$notifications_msg" -gt 0 ] || [ "$notifications_mention" -gt 0 ]; then
+ echo "# $notifications_msg / $notifications_mention"
+ else
+ echo ""
+ fi
+fi
diff --git a/.config/polybar/scripts/notification-reddit/README.md b/.config/polybar/scripts/notification-reddit/README.md
new file mode 100644
index 0000000..ba9dad6
--- /dev/null
+++ b/.config/polybar/scripts/notification-reddit/README.md
@@ -0,0 +1,28 @@
+# Script: notification-reddit
+
+A script that shows if there are unread mails in your reddit inbox.
+
+
+
+
+## Dependencies
+
+* `curl`
+* `jq`
+
+
+## Configuration
+
+Open [reddit.com/prefs/feeds/](https://www.reddit.com/prefs/feeds/). Copy the `JSON` link from `your inbox` > `unread messages`.
+
+Add your username at the end of `USERAGENT` to create a unique string.
+
+
+## Module
+
+```ini
+[module/notification-reddit]
+type = custom/script
+exec = ~/polybar-scripts/notification-reddit.sh
+interval = 60
+```
diff --git a/.config/polybar/scripts/notification-reddit/notification-reddit.sh b/.config/polybar/scripts/notification-reddit/notification-reddit.sh
new file mode 100644
index 0000000..1bb09df
--- /dev/null
+++ b/.config/polybar/scripts/notification-reddit/notification-reddit.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+URL=""
+USERAGENT="polybar-scripts/notification-reddit:v1.0 u/reddituser"
+
+notifications=$(curl -sf --user-agent "$USERAGENT" "$URL" | jq '.["data"]["children"] | length')
+
+if [ -n "$notifications" ] && [ "$notifications" -gt 0 ]; then
+ echo "#1 $notifications"
+else
+ echo "#2"
+fi
diff --git a/.config/polybar/scripts/notification-reddit/screenshots/1.png b/.config/polybar/scripts/notification-reddit/screenshots/1.png
new file mode 100644
index 0000000..761b066
Binary files /dev/null and b/.config/polybar/scripts/notification-reddit/screenshots/1.png differ
diff --git a/.config/polybar/scripts/notification-spacex/README.md b/.config/polybar/scripts/notification-spacex/README.md
new file mode 100644
index 0000000..c7e01db
--- /dev/null
+++ b/.config/polybar/scripts/notification-spacex/README.md
@@ -0,0 +1,21 @@
+# Script: notification-spacex
+
+A script that shows when the next launch is planned.
+
+
+
+
+## Dependencies
+
+* `curl`
+* `jq`
+
+
+## Module
+
+```ini
+[module/notification-spacex]
+type = custom/script
+exec = ~/polybar-scripts/notification-spacex.sh
+interval = 600
+```
diff --git a/.config/polybar/scripts/notification-spacex/notification-spacex.sh b/.config/polybar/scripts/notification-spacex/notification-spacex.sh
new file mode 100644
index 0000000..2337a4f
--- /dev/null
+++ b/.config/polybar/scripts/notification-spacex/notification-spacex.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+spacex_launch=$(curl -sf https://api.spacexdata.com/v5/launches/next)
+
+if [ -n "$spacex_launch" ]; then
+ spacex_precision=$(echo "$spacex_launch" | jq -r '.date_precision' )
+ spacex_timestamp=$(echo "$spacex_launch" | jq -r '.date_unix' )
+ spacex_duration=$((spacex_timestamp - $(date +%s)))
+
+ if [ "$spacex_precision" = "hour" ] && [ "$spacex_duration" -lt 43200 ] && [ "$spacex_duration" -gt 0 ]; then
+ echo "# $(date +"%H:%M" -u --date @$spacex_duration)"
+ else
+ echo ""
+ fi
+else
+ echo ""
+fi
diff --git a/.config/polybar/scripts/notification-spacex/screenshots/1.png b/.config/polybar/scripts/notification-spacex/screenshots/1.png
new file mode 100644
index 0000000..500ddeb
Binary files /dev/null and b/.config/polybar/scripts/notification-spacex/screenshots/1.png differ
diff --git a/.config/polybar/scripts/notification-xkcd/README.md b/.config/polybar/scripts/notification-xkcd/README.md
new file mode 100644
index 0000000..e59b12f
--- /dev/null
+++ b/.config/polybar/scripts/notification-xkcd/README.md
@@ -0,0 +1,26 @@
+# Script: notification-xkcd
+
+Displays the current xkcd comic and whether there are any new ones in polybar, written in python.
+
+
+
+
+
+## Dependencies
+
+* [`Python: requests`](https://pypi.org/project/requests/)
+
+
+## Configuration
+
+To set the icon or the location of the save file, edit `icon` or `latest_file` in `notification-xkcd.py`. Note that you cannot use `~` to indicate your home directory, as python needs a full path by default.
+
+## Module
+
+```ini
+[module/notification-xkcd]
+type = custom/script
+exec = ~/polybar-scripts/notification-xkcd.py
+click-left = xdg-open https://xkcd.com/ && ~/polybar-scripts/notification-xkcd.py read
+interval = 60
+```
diff --git a/.config/polybar/scripts/notification-xkcd/notification-xkcd.py b/.config/polybar/scripts/notification-xkcd/notification-xkcd.py
new file mode 100755
index 0000000..af5595e
--- /dev/null
+++ b/.config/polybar/scripts/notification-xkcd/notification-xkcd.py
@@ -0,0 +1,59 @@
+#!/usr/bin/env python3
+
+import requests
+from sys import argv
+
+latest_file = "/home/user/polybar-scripts/notification-xkcd-latest"
+icon = "#"
+
+
+read = False
+if len(argv) > 1:
+ if argv[1] == "read":
+ read = True
+
+
+def useFile(doc, mode, write):
+ f = open(doc, mode)
+ if mode == 'r':
+ doc = f.read()
+ f.close()
+ return doc
+ else:
+ f.write(write)
+ f.close()
+
+try:
+ latest = int(useFile(latest_file, 'r', '')[0:4])
+except FileNotFoundError:
+ useFile(latest_file, 'x', "2350")
+ latest = 2350
+
+newComic = False
+while True:
+ try:
+ status = requests.get('https://www.xkcd.com/' + str(latest + 1) + '/').status_code
+ except requests.exceptions.ConnectionError:
+ status = 404
+
+ if status == 200:
+ latest += 1
+ newComic = True
+
+ elif status == 404:
+ toPrint = ""
+
+ if useFile(latest_file, 'r', '')[4:] == 'Unread':
+ toPrint = "New: "
+
+ if read:
+ toPrint = ""
+ useFile(latest_file, 'w', str(latest) + 'Read')
+ elif newComic:
+ useFile(latest_file, 'w', str(latest) + 'Unread')
+ toPrint = "New: "
+
+ toPrint += str(latest)
+ print(icon + toPrint)
+ break
+
diff --git a/.config/polybar/scripts/notification-xkcd/screenshots/1.png b/.config/polybar/scripts/notification-xkcd/screenshots/1.png
new file mode 100644
index 0000000..387cfdb
Binary files /dev/null and b/.config/polybar/scripts/notification-xkcd/screenshots/1.png differ
diff --git a/.config/polybar/scripts/notification-xkcd/screenshots/2.png b/.config/polybar/scripts/notification-xkcd/screenshots/2.png
new file mode 100644
index 0000000..9324c53
Binary files /dev/null and b/.config/polybar/scripts/notification-xkcd/screenshots/2.png differ
diff --git a/.config/polybar/scripts/openweathermap-detailed/README.md b/.config/polybar/scripts/openweathermap-detailed/README.md
new file mode 100644
index 0000000..b1fd019
--- /dev/null
+++ b/.config/polybar/scripts/openweathermap-detailed/README.md
@@ -0,0 +1,46 @@
+# Script: openweathermap-detailed
+
+A weather script that displays some weather information.
+
+It shows icons, temperatures and text for the current weather.
+
+
+
+
+## Dependencies
+
+* [OpenWeatherMap Key](https://openweathermap.org/appid)
+* [weather-icons](https://github.com/erikflowers/weather-icons) or [Font Awesome 5 Pro](https://fontawesome.com/changelog/latest)
+* `jq`
+
+
+## Configuration
+
+If `CITY` is left empty, the location is retrieved via the Mozilla Location API. `CITY` can either be a city ID (e.g. ID of Berlin is `2950159`), city name (e.g. `Berlin`) or city name + country code (e.g. `Berlin,DE`).
+
+Change these values:
+
+```sh
+KEY=""
+CITY=""
+UNITS="metric"
+SYMBOL="°"
+```
+
+
+## Module
+
+```ini
+[bar/polybar]
+...
+font-2 = Weather Icons:size=12;1
+...
+```
+
+```ini
+[module/openweathermap-detailed]
+type = custom/script
+exec = ~/polybar-scripts/openweathermap-detailed.sh
+interval = 600
+label-font = 3
+```
diff --git a/.config/polybar/scripts/openweathermap-detailed/openweathermap-detailed.sh b/.config/polybar/scripts/openweathermap-detailed/openweathermap-detailed.sh
new file mode 100644
index 0000000..f346f49
--- /dev/null
+++ b/.config/polybar/scripts/openweathermap-detailed/openweathermap-detailed.sh
@@ -0,0 +1,76 @@
+#!/bin/sh
+
+get_icon() {
+ case $1 in
+ # Icons for weather-icons
+ 01d) icon="";;
+ 01n) icon="";;
+ 02d) icon="";;
+ 02n) icon="";;
+ 03*) icon="";;
+ 04*) icon="";;
+ 09d) icon="";;
+ 09n) icon="";;
+ 10d) icon="";;
+ 10n) icon="";;
+ 11d) icon="";;
+ 11n) icon="";;
+ 13d) icon="";;
+ 13n) icon="";;
+ 50d) icon="";;
+ 50n) icon="";;
+ *) icon="";
+
+ # Icons for Font Awesome 5 Pro
+ #01d) icon="";;
+ #01n) icon="";;
+ #02d) icon="";;
+ #02n) icon="";;
+ #03d) icon="";;
+ #03n) icon="";;
+ #04*) icon="";;
+ #09*) icon="";;
+ #10d) icon="";;
+ #10n) icon="";;
+ #11*) icon="";;
+ #13*) icon="";;
+ #50*) icon="";;
+ #*) icon="";
+ esac
+
+ echo $icon
+}
+
+KEY=""
+CITY=""
+UNITS="metric"
+SYMBOL="°"
+
+API="https://api.openweathermap.org/data/2.5"
+
+if [ -n "$CITY" ]; then
+ if [ "$CITY" -eq "$CITY" ] 2>/dev/null; then
+ CITY_PARAM="id=$CITY"
+ else
+ CITY_PARAM="q=$CITY"
+ fi
+
+ weather=$(curl -sf "$API/weather?appid=$KEY&$CITY_PARAM&units=$UNITS")
+else
+ location=$(curl -sf "https://location.services.mozilla.com/v1/geolocate?key=geoclue")
+
+ if [ -n "$location" ]; then
+ location_lat="$(echo "$location" | jq '.location.lat')"
+ location_lon="$(echo "$location" | jq '.location.lng')"
+
+ weather=$(curl -sf "$API/weather?appid=$KEY&lat=$location_lat&lon=$location_lon&units=$UNITS")
+ fi
+fi
+
+if [ -n "$weather" ]; then
+ weather_desc=$(echo "$weather" | jq -r ".weather[0].description")
+ weather_temp=$(echo "$weather" | jq ".main.temp" | cut -d "." -f 1)
+ weather_icon=$(echo "$weather" | jq -r ".weather[0].icon")
+
+ echo "$(get_icon "$weather_icon")" "$weather_desc", "$weather_temp$SYMBOL"
+fi
diff --git a/.config/polybar/scripts/openweathermap-detailed/screenshots/1.png b/.config/polybar/scripts/openweathermap-detailed/screenshots/1.png
new file mode 100644
index 0000000..9c5a14c
Binary files /dev/null and b/.config/polybar/scripts/openweathermap-detailed/screenshots/1.png differ
diff --git a/.config/polybar/scripts/openweathermap-forecast/README.md b/.config/polybar/scripts/openweathermap-forecast/README.md
new file mode 100644
index 0000000..2e4260f
--- /dev/null
+++ b/.config/polybar/scripts/openweathermap-forecast/README.md
@@ -0,0 +1,44 @@
+# Script: openweathermap-forecast
+
+A weather script that displays a weather forecast.
+
+It shows icons and temperatures for the current weather and the 3 hour forecast.
+
+
+## Dependencies
+
+* [OpenWeatherMap Key](https://openweathermap.org/appid)
+* [weather-icons](https://github.com/erikflowers/weather-icons) or [Font Awesome 5 Pro](https://fontawesome.com/changelog/latest)
+* `jq`
+
+
+## Configuration
+
+If `CITY` is left empty, the location is retrieved via the Mozilla Location API. `CITY` can either be a city ID (e.g. ID of Berlin is `2950159`), city name (e.g. `Berlin`) or city name + country code (e.g. `Berlin,DE`).
+
+Change these values:
+
+```sh
+KEY=""
+CITY=""
+UNITS="metric"
+SYMBOL="°"
+```
+
+
+## Module
+
+```ini
+[bar/polybar]
+...
+font-2 = Weather Icons:size=12;1
+...
+```
+
+```ini
+[module/openweathermap-forecast]
+type = custom/script
+exec = ~/polybar-scripts/openweathermap-forecast.sh
+interval = 600
+label-font = 3
+```
diff --git a/.config/polybar/scripts/openweathermap-forecast/openweathermap-forecast.sh b/.config/polybar/scripts/openweathermap-forecast/openweathermap-forecast.sh
new file mode 100644
index 0000000..81af108
--- /dev/null
+++ b/.config/polybar/scripts/openweathermap-forecast/openweathermap-forecast.sh
@@ -0,0 +1,88 @@
+#!/bin/sh
+
+get_icon() {
+ case $1 in
+ # Icons for weather-icons
+ 01d) icon="";;
+ 01n) icon="";;
+ 02d) icon="";;
+ 02n) icon="";;
+ 03*) icon="";;
+ 04*) icon="";;
+ 09d) icon="";;
+ 09n) icon="";;
+ 10d) icon="";;
+ 10n) icon="";;
+ 11d) icon="";;
+ 11n) icon="";;
+ 13d) icon="";;
+ 13n) icon="";;
+ 50d) icon="";;
+ 50n) icon="";;
+ *) icon="";
+
+ # Icons for Font Awesome 5 Pro
+ #01d) icon="";;
+ #01n) icon="";;
+ #02d) icon="";;
+ #02n) icon="";;
+ #03d) icon="";;
+ #03n) icon="";;
+ #04*) icon="";;
+ #09*) icon="";;
+ #10d) icon="";;
+ #10n) icon="";;
+ #11*) icon="";;
+ #13*) icon="";;
+ #50*) icon="";;
+ #*) icon="";
+ esac
+
+ echo $icon
+}
+
+KEY=""
+CITY=""
+UNITS="metric"
+SYMBOL="°"
+
+API="https://api.openweathermap.org/data/2.5"
+
+if [ -n "$CITY" ]; then
+ if [ "$CITY" -eq "$CITY" ] 2>/dev/null; then
+ CITY_PARAM="id=$CITY"
+ else
+ CITY_PARAM="q=$CITY"
+ fi
+
+ current=$(curl -sf "$API/weather?appid=$KEY&$CITY_PARAM&units=$UNITS")
+ forecast=$(curl -sf "$API/forecast?appid=$KEY&$CITY_PARAM&units=$UNITS&cnt=1")
+else
+ location=$(curl -sf "https://location.services.mozilla.com/v1/geolocate?key=geoclue")
+
+ if [ -n "$location" ]; then
+ location_lat="$(echo "$location" | jq '.location.lat')"
+ location_lon="$(echo "$location" | jq '.location.lng')"
+
+ current=$(curl -sf "$API/weather?appid=$KEY&lat=$location_lat&lon=$location_lon&units=$UNITS")
+ forecast=$(curl -sf "$API/forecast?appid=$KEY&lat=$location_lat&lon=$location_lon&units=$UNITS&cnt=1")
+ fi
+fi
+
+if [ -n "$current" ] && [ -n "$forecast" ]; then
+ current_temp=$(echo "$current" | jq ".main.temp" | cut -d "." -f 1)
+ current_icon=$(echo "$current" | jq -r ".weather[0].icon")
+
+ forecast_temp=$(echo "$forecast" | jq ".list[].main.temp" | cut -d "." -f 1)
+ forecast_icon=$(echo "$forecast" | jq -r ".list[].weather[0].icon")
+
+ if [ "$current_temp" -gt "$forecast_temp" ]; then
+ trend=""
+ elif [ "$forecast_temp" -gt "$current_temp" ]; then
+ trend=""
+ else
+ trend=""
+ fi
+
+ echo "$(get_icon "$current_icon") $current_temp$SYMBOL $trend $(get_icon "$forecast_icon") $forecast_temp$SYMBOL"
+fi
diff --git a/.config/polybar/scripts/openweathermap-fullfeatured/README.md b/.config/polybar/scripts/openweathermap-fullfeatured/README.md
new file mode 100644
index 0000000..210a3a2
--- /dev/null
+++ b/.config/polybar/scripts/openweathermap-fullfeatured/README.md
@@ -0,0 +1,46 @@
+# Script: openweathermap-fullfeatured
+
+A weather script that shows a lot of information.
+
+It shows icons and temperatures for the current weather and the 3 hour forecast. It displays the duration to the next sunrise or sunset.
+
+
+
+
+## Dependencies
+
+* [OpenWeatherMap Key](https://openweathermap.org/appid)
+* [weather-icons](https://github.com/erikflowers/weather-icons) or [Font Awesome 5 Pro](https://fontawesome.com/changelog/latest)
+* `jq`
+
+
+## Configuration
+
+If `CITY` is left empty, the location is retrieved via the Mozilla Location API. `CITY` can either be a city ID (e.g. ID of Berlin is `2950159`), city name (e.g. `Berlin`) or city name + country code (e.g. `Berlin,DE`).
+
+Change these values:
+
+```sh
+KEY=""
+CITY=""
+UNITS="metric"
+SYMBOL="°"
+```
+
+
+## Module
+
+```ini
+[bar/polybar]
+...
+font-2 = Weather Icons:size=12;1
+...
+```
+
+```ini
+[module/openweathermap-fullfeatured]
+type = custom/script
+exec = ~/polybar-scripts/openweathermap-fullfeatured.sh
+interval = 600
+label-font = 3
+```
diff --git a/.config/polybar/scripts/openweathermap-fullfeatured/openweathermap-fullfeatured.sh b/.config/polybar/scripts/openweathermap-fullfeatured/openweathermap-fullfeatured.sh
new file mode 100644
index 0000000..bfa6193
--- /dev/null
+++ b/.config/polybar/scripts/openweathermap-fullfeatured/openweathermap-fullfeatured.sh
@@ -0,0 +1,113 @@
+#!/bin/sh
+
+get_icon() {
+ case $1 in
+ # Icons for weather-icons
+ 01d) icon="";;
+ 01n) icon="";;
+ 02d) icon="";;
+ 02n) icon="";;
+ 03*) icon="";;
+ 04*) icon="";;
+ 09d) icon="";;
+ 09n) icon="";;
+ 10d) icon="";;
+ 10n) icon="";;
+ 11d) icon="";;
+ 11n) icon="";;
+ 13d) icon="";;
+ 13n) icon="";;
+ 50d) icon="";;
+ 50n) icon="";;
+ *) icon="";
+
+ # Icons for Font Awesome 5 Pro
+ #01d) icon="";;
+ #01n) icon="";;
+ #02d) icon="";;
+ #02n) icon="";;
+ #03d) icon="";;
+ #03n) icon="";;
+ #04*) icon="";;
+ #09*) icon="";;
+ #10d) icon="";;
+ #10n) icon="";;
+ #11*) icon="";;
+ #13*) icon="";;
+ #50*) icon="";;
+ #*) icon="";
+ esac
+
+ echo $icon
+}
+
+get_duration() {
+
+ osname=$(uname -s)
+
+ case $osname in
+ *BSD) date -r "$1" -u +%H:%M;;
+ *) date --date="@$1" -u +%H:%M;;
+ esac
+
+}
+
+KEY=""
+CITY=""
+UNITS="metric"
+SYMBOL="°"
+
+API="https://api.openweathermap.org/data/2.5"
+
+if [ -n "$CITY" ]; then
+ if [ "$CITY" -eq "$CITY" ] 2>/dev/null; then
+ CITY_PARAM="id=$CITY"
+ else
+ CITY_PARAM="q=$CITY"
+ fi
+
+ current=$(curl -sf "$API/weather?appid=$KEY&$CITY_PARAM&units=$UNITS")
+ forecast=$(curl -sf "$API/forecast?appid=$KEY&$CITY_PARAM&units=$UNITS&cnt=1")
+else
+ location=$(curl -sf "https://location.services.mozilla.com/v1/geolocate?key=geoclue")
+
+ if [ -n "$location" ]; then
+ location_lat="$(echo "$location" | jq '.location.lat')"
+ location_lon="$(echo "$location" | jq '.location.lng')"
+
+ current=$(curl -sf "$API/weather?appid=$KEY&lat=$location_lat&lon=$location_lon&units=$UNITS")
+ forecast=$(curl -sf "$API/forecast?appid=$KEY&lat=$location_lat&lon=$location_lon&units=$UNITS&cnt=1")
+ fi
+fi
+
+if [ -n "$current" ] && [ -n "$forecast" ]; then
+ current_temp=$(echo "$current" | jq ".main.temp" | cut -d "." -f 1)
+ current_icon=$(echo "$current" | jq -r ".weather[0].icon")
+
+ forecast_temp=$(echo "$forecast" | jq ".list[].main.temp" | cut -d "." -f 1)
+ forecast_icon=$(echo "$forecast" | jq -r ".list[].weather[0].icon")
+
+
+ if [ "$current_temp" -gt "$forecast_temp" ]; then
+ trend=""
+ elif [ "$forecast_temp" -gt "$current_temp" ]; then
+ trend=""
+ else
+ trend=""
+ fi
+
+
+ sun_rise=$(echo "$current" | jq ".sys.sunrise")
+ sun_set=$(echo "$current" | jq ".sys.sunset")
+ now=$(date +%s)
+
+ if [ "$sun_rise" -gt "$now" ]; then
+ daytime=" $(get_duration "$((sun_rise-now))")"
+ elif [ "$sun_set" -gt "$now" ]; then
+ daytime=" $(get_duration "$((sun_set-now))")"
+ else
+ daytime=" $(get_duration "$((sun_rise-now))")"
+ fi
+
+ echo "$(get_icon "$current_icon") $current_temp$SYMBOL $trend $(get_icon "$forecast_icon") $forecast_temp$SYMBOL $daytime"
+fi
diff --git a/.config/polybar/scripts/openweathermap-fullfeatured/screenshots/1.png b/.config/polybar/scripts/openweathermap-fullfeatured/screenshots/1.png
new file mode 100644
index 0000000..a3f17ed
Binary files /dev/null and b/.config/polybar/scripts/openweathermap-fullfeatured/screenshots/1.png differ
diff --git a/.config/polybar/scripts/openweathermap-simple/README.md b/.config/polybar/scripts/openweathermap-simple/README.md
new file mode 100644
index 0000000..7f24bfd
--- /dev/null
+++ b/.config/polybar/scripts/openweathermap-simple/README.md
@@ -0,0 +1,46 @@
+# Script: openweathermap-simple
+
+A weather script that displays some weather information.
+
+It shows icons and temperatures for the current weather.
+
+
+
+
+## Dependencies
+
+* [OpenWeatherMap Key](https://openweathermap.org/appid)
+* [weather-icons](https://github.com/erikflowers/weather-icons) or [Font Awesome 5 Pro](https://fontawesome.com/changelog/latest)
+* `jq`
+
+
+## Configuration
+
+If `CITY` is left empty, the location is retrieved via the Mozilla Location API. `CITY` can either be a city ID (e.g. ID of Berlin is `2950159`), city name (e.g. `Berlin`) or city name + country code (e.g. `Berlin,DE`).
+
+Change these values:
+
+```sh
+KEY=""
+CITY=""
+UNITS="metric"
+SYMBOL="°"
+```
+
+
+## Module
+
+```ini
+[bar/polybar]
+...
+font-2 = Weather Icons:size=12;1
+...
+```
+
+```ini
+[module/openweathermap-simple]
+type = custom/script
+exec = ~/polybar-scripts/openweathermap-simple.sh
+interval = 600
+label-font = 3
+```
diff --git a/.config/polybar/scripts/openweathermap-simple/openweathermap-simple.sh b/.config/polybar/scripts/openweathermap-simple/openweathermap-simple.sh
new file mode 100644
index 0000000..01848be
--- /dev/null
+++ b/.config/polybar/scripts/openweathermap-simple/openweathermap-simple.sh
@@ -0,0 +1,75 @@
+#!/bin/sh
+
+get_icon() {
+ case $1 in
+ # Icons for weather-icons
+ 01d) icon="";;
+ 01n) icon="";;
+ 02d) icon="";;
+ 02n) icon="";;
+ 03*) icon="";;
+ 04*) icon="";;
+ 09d) icon="";;
+ 09n) icon="";;
+ 10d) icon="";;
+ 10n) icon="";;
+ 11d) icon="";;
+ 11n) icon="";;
+ 13d) icon="";;
+ 13n) icon="";;
+ 50d) icon="";;
+ 50n) icon="";;
+ *) icon="";
+
+ # Icons for Font Awesome 5 Pro
+ #01d) icon="";;
+ #01n) icon="";;
+ #02d) icon="";;
+ #02n) icon="";;
+ #03d) icon="";;
+ #03n) icon="";;
+ #04*) icon="";;
+ #09*) icon="";;
+ #10d) icon="";;
+ #10n) icon="";;
+ #11*) icon="";;
+ #13*) icon="";;
+ #50*) icon="";;
+ #*) icon="";
+ esac
+
+ echo $icon
+}
+
+KEY=""
+CITY=""
+UNITS="metric"
+SYMBOL="°"
+
+API="https://api.openweathermap.org/data/2.5"
+
+if [ -n "$CITY" ]; then
+ if [ "$CITY" -eq "$CITY" ] 2>/dev/null; then
+ CITY_PARAM="id=$CITY"
+ else
+ CITY_PARAM="q=$CITY"
+ fi
+
+ weather=$(curl -sf "$API/weather?appid=$KEY&$CITY_PARAM&units=$UNITS")
+else
+ location=$(curl -sf "https://location.services.mozilla.com/v1/geolocate?key=geoclue")
+
+ if [ -n "$location" ]; then
+ location_lat="$(echo "$location" | jq '.location.lat')"
+ location_lon="$(echo "$location" | jq '.location.lng')"
+
+ weather=$(curl -sf "$API/weather?appid=$KEY&lat=$location_lat&lon=$location_lon&units=$UNITS")
+ fi
+fi
+
+if [ -n "$weather" ]; then
+ weather_temp=$(echo "$weather" | jq ".main.temp" | cut -d "." -f 1)
+ weather_icon=$(echo "$weather" | jq -r ".weather[0].icon")
+
+ echo "$(get_icon "$weather_icon")" "$weather_temp$SYMBOL"
+fi
diff --git a/.config/polybar/scripts/openweathermap-simple/screenshots/1.png b/.config/polybar/scripts/openweathermap-simple/screenshots/1.png
new file mode 100644
index 0000000..24a9294
Binary files /dev/null and b/.config/polybar/scripts/openweathermap-simple/screenshots/1.png differ
diff --git a/.config/polybar/scripts/pipewire-microphone/README.md b/.config/polybar/scripts/pipewire-microphone/README.md
new file mode 100644
index 0000000..e5412ea
--- /dev/null
+++ b/.config/polybar/scripts/pipewire-microphone/README.md
@@ -0,0 +1,19 @@
+# Script: pipewire-microphone
+
+A script for showing and toggling the mute state of the PipeWire default microphone.
+
+
+## Dependencies
+
+* pactl (libpulse)
+
+
+## Module
+
+``` ini
+[module/pipewire-microphone]
+type = custom/script
+exec = $HOME/.config/polybar/polybar-scripts/polybar-scripts/pipewire-microphone/pipewire-microphone.sh
+tail = true
+click-left = $HOME/.config/polybar/polybar-scripts/polybar-scripts/pipewire-microphone/pipewire-microphone.sh --toggle &
+```
diff --git a/.config/polybar/scripts/pipewire-microphone/pipewire-microphone.sh b/.config/polybar/scripts/pipewire-microphone/pipewire-microphone.sh
new file mode 100644
index 0000000..9a4c77a
--- /dev/null
+++ b/.config/polybar/scripts/pipewire-microphone/pipewire-microphone.sh
@@ -0,0 +1,39 @@
+#!/bin/sh
+
+get_mic_default() {
+ pactl info | awk '/Default Source:/ {print $3}'
+}
+
+is_mic_muted() {
+ pactl get-source-mute "$(get_mic_default)" | awk '{print $2}'
+}
+
+get_mic_status() {
+ if [ "$(is_mic_muted)" = "yes" ]; then
+ printf "%s\n" "#1"
+ else
+ printf "%s\n" "#2"
+ fi
+}
+
+listen() {
+ get_mic_status
+ LANG=EN; pactl subscribe | while read -r event; do
+ if printf "%s\n" "${event}" | grep -qE '(source|server)'; then
+ get_mic_status
+ fi
+ done
+}
+
+toggle() {
+ pactl set-source-mute @DEFAULT_SOURCE@ toggle
+}
+
+case "${1}" in
+ --toggle)
+ toggle
+ ;;
+ *)
+ listen
+ ;;
+esac
diff --git a/.config/polybar/scripts/pipewire-simple/README.md b/.config/polybar/scripts/pipewire-simple/README.md
new file mode 100644
index 0000000..a94933f
--- /dev/null
+++ b/.config/polybar/scripts/pipewire-simple/README.md
@@ -0,0 +1,27 @@
+# Script: pipewire-simple
+
+A script to control pipewire with your mouse buttons and scroll wheel.
+
+
+
+
+## Dependencies
+
+* `pactl`
+* `pamixer`
+
+Maybe `pavucontrol` is a good idea. In the example it is opened with a right mouse click.
+
+
+## Module
+
+```ini
+[module/pipewire-simple]
+type = custom/script
+exec = ~/polybar-scripts/pipewire-simple.sh
+interval = 3
+click-right = exec pavucontrol &
+click-left = ~/polybar-scripts/pipewire-simple.sh --mute &
+scroll-up = ~/polybar-scripts/pipewire-simple.sh --up &
+scroll-down = ~/polybar-scripts/pipewire-simple.sh --down &
+```
diff --git a/.config/polybar/scripts/pipewire-simple/pipewire-simple.sh b/.config/polybar/scripts/pipewire-simple/pipewire-simple.sh
new file mode 100644
index 0000000..cb9da4f
--- /dev/null
+++ b/.config/polybar/scripts/pipewire-simple/pipewire-simple.sh
@@ -0,0 +1,31 @@
+#!/bin/sh
+
+getDefaultSink() {
+ defaultSink=$(pactl info | awk -F : '/Default Sink:/{print $2}')
+ description=$(pactl list sinks | sed -n "/${defaultSink}/,/Description/s/^\s*Description: \(.*\)/\1/p")
+ echo "${description}"
+}
+
+getDefaultSource() {
+ defaultSource=$(pactl info | awk -F : '/Default Source:/{print $2}')
+ description=$(pactl list sources | sed -n "/${defaultSource}/,/Description/s/^\s*Description: \(.*\)/\1/p")
+ echo "${description}"
+}
+
+VOLUME=$(pamixer --get-volume-human)
+SINK=$(getDefaultSink)
+SOURCE=$(getDefaultSource)
+
+case $1 in
+ "--up")
+ pamixer --increase 10
+ ;;
+ "--down")
+ pamixer --decrease 10
+ ;;
+ "--mute")
+ pamixer --toggle-mute
+ ;;
+ *)
+ echo "Source: ${SOURCE} | Sink: ${VOLUME} ${SINK}"
+esac
diff --git a/.config/polybar/scripts/pipewire-simple/screenshots/1.png b/.config/polybar/scripts/pipewire-simple/screenshots/1.png
new file mode 100644
index 0000000..78e6a11
Binary files /dev/null and b/.config/polybar/scripts/pipewire-simple/screenshots/1.png differ
diff --git a/.config/polybar/scripts/player-cmus/README.md b/.config/polybar/scripts/player-cmus/README.md
new file mode 100644
index 0000000..b13b84c
--- /dev/null
+++ b/.config/polybar/scripts/player-cmus/README.md
@@ -0,0 +1,18 @@
+# Script: player-cmus
+
+A script that displays information about the current track (artist, title, position, duration).
+
+
+
+
+## Module
+
+```ini
+[module/player-cmus]
+type = custom/script
+exec = ~/polybar-scripts/player-cmus.sh
+interval = 5
+click-left = cmus-remote -n &
+click-right = cmus-remote -r &
+click-middle = cmus-remote -u &
+```
diff --git a/.config/polybar/scripts/player-cmus/player-cmus.sh b/.config/polybar/scripts/player-cmus/player-cmus.sh
new file mode 100644
index 0000000..72d744e
--- /dev/null
+++ b/.config/polybar/scripts/player-cmus/player-cmus.sh
@@ -0,0 +1,42 @@
+#!/bin/sh
+
+if info=$(cmus-remote -Q 2> /dev/null); then
+ status=$(echo "$info" | grep -v "set " | grep -v "tag " | grep "status " | cut -d ' ' -f 2)
+
+ if [ "$status" = "playing" ] || [ "$status" = "paused" ] || [ "$status" = "stopped" ]; then
+ title=$(echo "$info" | grep -v 'set ' | grep " title " | cut -d ' ' -f 3-)
+ artist=$(echo "$info" | grep -v 'set ' | grep " artist " | cut -d ' ' -f 3-)
+ position=$(echo "$info" | grep -v "set " | grep -v "tag " | grep "position " | cut -d ' ' -f 2)
+ duration=$(echo "$info" | grep -v "set " | grep -v "tag " | grep "duration " | cut -d ' ' -f 2)
+
+ if [ "$artist" ] || [ "$title" ]; then
+ if [ "$duration" -ge 0 ]; then
+ pos_minutes=$(printf "%02d" $((position / 60)))
+ pos_seconds=$(printf "%02d" $((position % 60)))
+
+ dur_minutes=$(printf "%02d" $((duration / 60)))
+ dur_seconds=$(printf "%02d" $((duration % 60)))
+
+ info_string="| $pos_minutes:$pos_seconds / $dur_minutes:$dur_seconds"
+ fi
+
+ info_string="$artist - $title $info_string"
+
+ if [ "$status" = "playing" ]; then
+ echo "#1 $info_string"
+ elif [ "$status" = "paused" ]; then
+ echo "#2 $info_string"
+ elif [ "$status" = "stopped" ]; then
+ echo "#3 $info_string"
+ else
+ echo ""
+ fi
+ else
+ echo ""
+ fi
+ else
+ echo ""
+ fi
+else
+ echo ""
+fi
diff --git a/.config/polybar/scripts/player-cmus/screenshots/1.png b/.config/polybar/scripts/player-cmus/screenshots/1.png
new file mode 100644
index 0000000..11f7cde
Binary files /dev/null and b/.config/polybar/scripts/player-cmus/screenshots/1.png differ
diff --git a/.config/polybar/scripts/player-moc/README.md b/.config/polybar/scripts/player-moc/README.md
new file mode 100644
index 0000000..e45fa7a
--- /dev/null
+++ b/.config/polybar/scripts/player-moc/README.md
@@ -0,0 +1,16 @@
+# Script: player-moc
+
+A small script that shows the current song. You can also control mocp.
+
+
+## Module
+
+```ini
+[module/player-moc]
+type = custom/script
+exec = ~/polybar-scripts/player-moc.sh
+interval = 3
+click-left = mocp -f &
+click-right = mocp -r &
+click-middle = mocp -G &
+```
diff --git a/.config/polybar/scripts/player-moc/player-moc.sh b/.config/polybar/scripts/player-moc/player-moc.sh
new file mode 100644
index 0000000..af34ed2
--- /dev/null
+++ b/.config/polybar/scripts/player-moc/player-moc.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+if [ "$(mocp -Q %state)" != "STOP" ];then
+ SONG=$(mocp -Q %song)
+
+ if [ -n "$SONG" ]; then
+ echo "$SONG - $(mocp -Q %album)"
+ else
+ basename "$(mocp -Q %file)"
+ fi
+else
+ echo ""
+fi
diff --git a/.config/polybar/scripts/player-mpris-simple/README.md b/.config/polybar/scripts/player-mpris-simple/README.md
new file mode 100644
index 0000000..7f4b59f
--- /dev/null
+++ b/.config/polybar/scripts/player-mpris-simple/README.md
@@ -0,0 +1,23 @@
+# Script: player-mpris-simple
+
+A small script that shows the current track.
+
+
+
+
+## Dependencies
+
+* [playerctl](https://github.com/acrisci/playerctl)
+
+
+## Module
+
+```ini
+[module/player-mpris-simple]
+type = custom/script
+exec = ~/polybar-scripts/player-mpris-simple.sh
+interval = 3
+click-left = playerctl previous &
+click-right = playerctl next &
+click-middle = playerctl play-pause &
+```
diff --git a/.config/polybar/scripts/player-mpris-simple/player-mpris-simple.sh b/.config/polybar/scripts/player-mpris-simple/player-mpris-simple.sh
new file mode 100755
index 0000000..65cc8bf
--- /dev/null
+++ b/.config/polybar/scripts/player-mpris-simple/player-mpris-simple.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+player_status=$(playerctl status 2> /dev/null)
+
+if [ "$player_status" = "Playing" ]; then
+ echo " $(playerctl metadata artist) - $(playerctl metadata title)"
+elif [ "$player_status" = "Paused" ]; then
+ echo " $(playerctl metadata artist) - $(playerctl metadata title)"
+else
+ echo ""
+fi
diff --git a/.config/polybar/scripts/player-mpris-simple/screenshots/1.png b/.config/polybar/scripts/player-mpris-simple/screenshots/1.png
new file mode 100644
index 0000000..16a43d1
Binary files /dev/null and b/.config/polybar/scripts/player-mpris-simple/screenshots/1.png differ
diff --git a/.config/polybar/scripts/player-mpris-tail/README.md b/.config/polybar/scripts/player-mpris-tail/README.md
new file mode 100644
index 0000000..8af4371
--- /dev/null
+++ b/.config/polybar/scripts/player-mpris-tail/README.md
@@ -0,0 +1,167 @@
+# Script: player-mpris-tail
+
+This script displays the current track and the play-pause status without polling. Information is obtained by listening to MPRIS events, so it is updated instantaneously on change.
+
+ 
+
+
+## Dependencies
+
+* `python-dbus`
+* `python-gobject`
+* `python-gi`
+
+
+## Configuration
+
+The format of the output can be defined by passing an `-f` or `--format` argument. This argument supports metadata replacement using `{tag}` (e.g. `{title}`) as well as more advanced formatting, described below.
+
+Players can be blacklisted by passing a `-b` or `--blacklist` argument. As an example, VLC can be blacklisted by passing `-b vlc`. To get a list of the current running players (and their status), run the script as `player-mpris-tail.py list`.
+
+
+### Commands
+
+The current player can be controlled by passing one of the following commands:
+
+Command | Description
+---|---
+play | Play the current track
+pause | Pause the currently playing track
+play-pause | Play the current track or unpause it if currently paused
+stop | Stop playback
+previous | Move to the previous track
+next | Move to the next track
+raise | Tell the current player to focus its window
+
+General information about the current state can be printed using the following commands:
+
+Command | Description
+---|---
+status | Print the normal output and exit immediately
+current | Print the currently detected player and its status
+list | List the detected players and their status
+metadata | Print the metadata object for the current track
+
+
+### Arguments
+
+The following arguments are supported:
+
+Argument | Description | Default
+---|---|---
+-b, --blacklist | Blacklist / Ignore the given player
+-w, --whitelist | Whitelist / Permit the given player
+-f, --format | Use the given `format` string | `{icon} {artist} - {title}`
+--truncate-text | Use the given string as the end of truncated text | `…`
+--icon-playing | Use the given text as the playing icon | `⏵`
+--icon-paused | Use the given text as the paused icon | `⏸`
+--icon-stopped | Use the given text as the stopped icon | `⏹`
+--icon-none | Use the given text as the icon for when no player is active | ``
+
+
+### Formatting
+
+Tags can be printed by surrounding them with `{` and `}`. Polybar formatting can also be given and will be passed through, including substituted tags and formatters.
+
+
+### Tags
+
+The supported tags are:
+
+Tag | Description
+---|---
+artist | The artist of the current track
+album | The album of the current track
+title | The title of the current track
+track | The track number of the current track
+length | The length of the current track
+fmt-length | The formatted length of the current track ([hours:]minutes:seconds)
+position | The track current time position
+genre | The genre of the current track
+disc | The disc number of the current track
+date | The date of the current track
+year | The year of the current track
+cover | The URL of the cover of the current track
+icon | The icon for the current status (playing / paused / stopped / none)
+icon-reversed | The pause icon when playing, else the play icon
+
+
+### String formatters
+
+Parts of the `format` string can be manipulated by surrounding them with `{:` and `:}` and prepending a formatter followed by a `:` (e.g. `{:t20:by {artist}:}`)
+
+The following formatters are supported:
+
+Formatter | Argument | Description | Example | Output
+---|---|---|---|---
+`tag` | | Only print the string if `tag` exists | `{:album: on {album}:}` | ` on Album Name`
+w | Number | Limit the width of the string to `number` | `{:w3:Hello:}` | `Hel`
+t | Number | Truncate width of the string to `number`. If the string is shorter than or equal to `number` it is printed as given, else the string is truncated and appended a truncator text | `{:t3:Hello:}` | `He…`
+
+
+## Module
+
+### Basic output
+
+```ini
+[module/player-mpris-tail]
+type = custom/script
+exec = ~/polybar-scripts/player-mpris-tail.py -f '{icon} {artist} - {title}'
+tail = true
+```
+
+Example: `⏵ Artist - Title`
+
+
+### Basic output and mouse controls
+
+```ini
+[module/player-mpris-tail]
+type = custom/script
+exec = ~/polybar-scripts/player-mpris-tail.py -f '{icon} {artist} - {title}'
+tail = true
+click-left = ~/polybar-scripts/player-mpris-tail.py previous &
+click-right = ~/polybar-scripts/player-mpris-tail.py next &
+click-middle = ~/polybar-scripts/player-mpris-tail.py play-pause &
+```
+
+Example: `⏵ Artist - Title`
+
+
+### Output using formatters
+
+```ini
+[module/player-mpris-tail]
+type = custom/script
+exec = ~/polybar-scripts/player-mpris-tail.py -f '{icon} {:artist:t5:{artist}:}{:artist: - :}{:t4:{title}:}'
+tail = true
+click-left = ~/polybar-scripts/player-mpris-tail.py previous &
+click-right = ~/polybar-scripts/player-mpris-tail.py next &
+click-middle = ~/polybar-scripts/player-mpris-tail.py play-pause &
+```
+
+Example: `⏵ Artis… - Titl…` or `⏵ Titl…`
+
+
+### Output using formatters and Polybar action handlers
+
+```ini
+[module/player-mpris-tail]
+type = custom/script
+exec = ~/polybar-scripts/player-mpris-tail.py -f '{icon} {:artist:t18:{artist}:}{:artist: - :}{:t20:{title}:} %{A1:~/polybar-scripts/player-mpris-tail.py previous:} ⏮ %{A} %{A1:~/polybar-scripts/player-mpris-tail.py play-pause:} {icon-reversed} %{A} %{A1:~/polybar-scripts/player-mpris-tail.py next:} ⏭ %{A}'
+tail = true
+```
+
+Example: `⏵ Artis… - Titl… ⏮ ⏸ ⏭ ` or `⏵ Titl… ⏮ ⏸ ⏭ ` or `⏸ Titl… ⏮ ⏵ ⏭ `
+
+
+### Output using formatters, Polybar action handlers and blacklisting
+
+```ini
+[module/player-mpris-tail]
+type = custom/script
+exec = ~/polybar-scripts/player-mpris-tail.py -f '{icon} {:artist:t18:{artist}:}{:artist: - :}{:t20:{title}:} %{A1:~/polybar-scripts/player-mpris-tail.py previous -b vlc -b plasma-browser-integration:} ⏮ %{A} %{A1:~/polybar-scripts/player-mpris-tail.py play-pause -b vlc -b plasma-browser-integration:} {icon-reversed} %{A} %{A1:~/polybar-scripts/player-mpris-tail.py next -b vlc -b plasma-browser-integration:} ⏭ %{A}' -b vlc -b plasma-browser-integration
+tail = true
+```
+
+Example: `⏵ Artis… - Titl… ⏮ ⏸ ⏭ ` or `⏵ Titl… ⏮ ⏸ ⏭ ` or `⏸ Titl… ⏮ ⏵ ⏭ `
diff --git a/.config/polybar/scripts/player-mpris-tail/player-mpris-tail.py b/.config/polybar/scripts/player-mpris-tail/player-mpris-tail.py
new file mode 100755
index 0000000..93e7c27
--- /dev/null
+++ b/.config/polybar/scripts/player-mpris-tail/player-mpris-tail.py
@@ -0,0 +1,554 @@
+#!/usr/bin/env python3
+
+import sys
+import dbus
+import os
+from operator import itemgetter
+import argparse
+import re
+from urllib.parse import unquote
+import time
+from dbus.mainloop.glib import DBusGMainLoop
+from gi.repository import GLib
+DBusGMainLoop(set_as_default=True)
+
+
+FORMAT_STRING = '{icon} {artist} - {title}'
+FORMAT_REGEX = re.compile(r'(\{:(?P.*?)(:(?P[wt])(?P\d+))?:(?P.*?):\})', re.I)
+FORMAT_TAG_REGEX = re.compile(r'(?P[wt])(?P\d+)')
+SAFE_TAG_REGEX = re.compile(r'[{}]')
+
+class PlayerManager:
+ def __init__(self, filter_list, block_mode = True, connect = True):
+ self.filter_list = filter_list
+ self.block_mode = block_mode
+ self._connect = connect
+ self._session_bus = dbus.SessionBus()
+ self.players = {}
+
+ self.print_queue = []
+ self.connected = False
+ self.player_states = {}
+
+ self.refreshPlayerList()
+
+ if self._connect:
+ self.connect()
+ loop = GLib.MainLoop()
+ try:
+ loop.run()
+ except KeyboardInterrupt:
+ print("interrupt received, stopping…")
+
+ def connect(self):
+ self._session_bus.add_signal_receiver(self.onOwnerChangedName, 'NameOwnerChanged')
+ self._session_bus.add_signal_receiver(self.onChangedProperties, 'PropertiesChanged',
+ path = '/org/mpris/MediaPlayer2',
+ sender_keyword='sender')
+
+ def onChangedProperties(self, interface, properties, signature, sender = None):
+ if sender in self.players:
+ player = self.players[sender]
+ # If we know this player, but haven't been able to set up a signal handler
+ if 'properties_changed' not in player._signals:
+ # Then trigger the signal handler manually
+ player.onPropertiesChanged(interface, properties, signature)
+ else:
+ # If we don't know this player, get its name and add it
+ bus_name = self.getBusNameFromOwner(sender)
+ if bus_name is None:
+ return
+ self.addPlayer(bus_name, sender)
+ player = self.players[sender]
+ player.onPropertiesChanged(interface, properties, signature)
+
+ def onOwnerChangedName(self, bus_name, old_owner, new_owner):
+ if self.busNameIsAPlayer(bus_name):
+ if new_owner and not old_owner:
+ self.addPlayer(bus_name, new_owner)
+ elif old_owner and not new_owner:
+ self.removePlayer(old_owner)
+ else:
+ self.changePlayerOwner(bus_name, old_owner, new_owner)
+
+ def getBusNameFromOwner(self, owner):
+ player_bus_names = [ bus_name for bus_name in self._session_bus.list_names() if self.busNameIsAPlayer(bus_name) ]
+ for player_bus_name in player_bus_names:
+ player_bus_owner = self._session_bus.get_name_owner(player_bus_name)
+ if owner == player_bus_owner:
+ return player_bus_name
+
+ def busNameIsAPlayer(self, bus_name):
+ if bus_name.startswith('org.mpris.MediaPlayer2') is False:
+ return False
+ name = bus_name.split('.')[3]
+ if self.block_mode is True:
+ return name not in self.filter_list
+ return name in self.filter_list
+
+ def refreshPlayerList(self):
+ player_bus_names = [ bus_name for bus_name in self._session_bus.list_names() if self.busNameIsAPlayer(bus_name) ]
+ for player_bus_name in player_bus_names:
+ self.addPlayer(player_bus_name)
+ if self.connected != True:
+ self.connected = True
+ self.printQueue()
+
+ def addPlayer(self, bus_name, owner = None):
+ player = Player(self._session_bus, bus_name, owner = owner, connect = self._connect, _print = self.print)
+ self.players[player.owner] = player
+
+ def removePlayer(self, owner):
+ if owner in self.players:
+ self.players[owner].disconnect()
+ del self.players[owner]
+ # If there are no more players, clear the output
+ if len(self.players) == 0:
+ _printFlush(ICON_NONE)
+ # Else, print the output of the next active player
+ else:
+ players = self.getSortedPlayerOwnerList()
+ if len(players) > 0:
+ self.players[players[0]].printStatus()
+
+ def changePlayerOwner(self, bus_name, old_owner, new_owner):
+ player = Player(self._session_bus, bus_name, owner = new_owner, connect = self._connect, _print = self.print)
+ self.players[new_owner] = player
+ del self.players[old_owner]
+
+ # Get a list of player owners sorted by current status and age
+ def getSortedPlayerOwnerList(self):
+ players = [
+ {
+ 'number': int(owner.split('.')[-1]),
+ 'status': 2 if player.status == 'playing' else 1 if player.status == 'paused' else 0,
+ 'owner': owner
+ }
+ for owner, player in self.players.items()
+ ]
+ return [ info['owner'] for info in reversed(sorted(players, key=itemgetter('status', 'number'))) ]
+
+ # Get latest player that's currently playing
+ def getCurrentPlayer(self):
+ playing_players = [
+ player_owner for player_owner in self.getSortedPlayerOwnerList()
+ if
+ self.players[player_owner].status == 'playing' or
+ self.players[player_owner].status == 'paused'
+ ]
+ return self.players[playing_players[0]] if playing_players else None
+
+ def print(self, status, player):
+ self.player_states[player.bus_name] = status
+
+ if self.connected:
+ current_player = self.getCurrentPlayer()
+ if current_player != None:
+ _printFlush(self.player_states[current_player.bus_name])
+ else:
+ _printFlush(ICON_STOPPED)
+ else:
+ self.print_queue.append([status, player])
+
+ def printQueue(self):
+ for args in self.print_queue:
+ self.print(args[0], args[1])
+ self.print_queue.clear()
+
+
+class Player:
+ def __init__(self, session_bus, bus_name, owner = None, connect = True, _print = None):
+ self._session_bus = session_bus
+ self.bus_name = bus_name
+ self._disconnecting = False
+ self.__print = _print
+
+ self.metadata = {
+ 'artist' : '',
+ 'album' : '',
+ 'title' : '',
+ 'track' : 0
+ }
+
+ self._rate = 1.
+ self._positionAtLastUpdate = 0.
+ self._timeAtLastUpdate = time.time()
+ self._positionTimerRunning = False
+
+ self._metadata = None
+ self.status = 'stopped'
+ self.icon = ICON_NONE
+ self.icon_reversed = ICON_PLAYING
+ if owner is not None:
+ self.owner = owner
+ else:
+ self.owner = self._session_bus.get_name_owner(bus_name)
+ self._obj = self._session_bus.get_object(self.bus_name, '/org/mpris/MediaPlayer2')
+ self._properties_interface = dbus.Interface(self._obj, dbus_interface='org.freedesktop.DBus.Properties')
+ self._introspect_interface = dbus.Interface(self._obj, dbus_interface='org.freedesktop.DBus.Introspectable')
+ self._media_interface = dbus.Interface(self._obj, dbus_interface='org.mpris.MediaPlayer2')
+ self._player_interface = dbus.Interface(self._obj, dbus_interface='org.mpris.MediaPlayer2.Player')
+ self._introspect = self._introspect_interface.get_dbus_method('Introspect', dbus_interface=None)
+ self._getProperty = self._properties_interface.get_dbus_method('Get', dbus_interface=None)
+ self._playerPlay = self._player_interface.get_dbus_method('Play', dbus_interface=None)
+ self._playerPause = self._player_interface.get_dbus_method('Pause', dbus_interface=None)
+ self._playerPlayPause = self._player_interface.get_dbus_method('PlayPause', dbus_interface=None)
+ self._playerStop = self._player_interface.get_dbus_method('Stop', dbus_interface=None)
+ self._playerPrevious = self._player_interface.get_dbus_method('Previous', dbus_interface=None)
+ self._playerNext = self._player_interface.get_dbus_method('Next', dbus_interface=None)
+ self._playerRaise = self._media_interface.get_dbus_method('Raise', dbus_interface=None)
+ self._signals = {}
+
+ self.refreshPosition()
+ self.refreshStatus()
+ self.refreshMetadata()
+
+ if connect:
+ self.printStatus()
+ self.connect()
+
+ def play(self):
+ self._playerPlay()
+ def pause(self):
+ self._playerPause()
+ def playpause(self):
+ self._playerPlayPause()
+ def stop(self):
+ self._playerStop()
+ def previous(self):
+ self._playerPrevious()
+ def next(self):
+ self._playerNext()
+ def raisePlayer(self):
+ self._playerRaise()
+
+ def connect(self):
+ if self._disconnecting is not True:
+ introspect_xml = self._introspect(self.bus_name, '/')
+ if 'TrackMetadataChanged' in introspect_xml:
+ self._signals['track_metadata_changed'] = self._session_bus.add_signal_receiver(self.onMetadataChanged, 'TrackMetadataChanged', self.bus_name)
+ self._signals['seeked'] = self._player_interface.connect_to_signal('Seeked', self.onSeeked)
+ self._signals['properties_changed'] = self._properties_interface.connect_to_signal('PropertiesChanged', self.onPropertiesChanged)
+
+ def disconnect(self):
+ self._disconnecting = True
+ for signal_name, signal_handler in list(self._signals.items()):
+ signal_handler.remove()
+ del self._signals[signal_name]
+
+ def refreshStatus(self):
+ # Some clients (VLC) will momentarily create a new player before removing it again
+ # so we can't be sure the interface still exists
+ try:
+ self.status = str(self._getProperty('org.mpris.MediaPlayer2.Player', 'PlaybackStatus')).lower()
+ self.updateIcon()
+ self.checkPositionTimer()
+ except dbus.exceptions.DBusException:
+ self.disconnect()
+
+ def refreshMetadata(self):
+ # Some clients (VLC) will momentarily create a new player before removing it again
+ # so we can't be sure the interface still exists
+ try:
+ self._metadata = self._getProperty('org.mpris.MediaPlayer2.Player', 'Metadata')
+ self._parseMetadata()
+ except dbus.exceptions.DBusException:
+ self.disconnect()
+
+ def updateIcon(self):
+ self.icon = (
+ ICON_PLAYING if self.status == 'playing' else
+ ICON_PAUSED if self.status == 'paused' else
+ ICON_STOPPED if self.status == 'stopped' else
+ ICON_NONE
+ )
+ self.icon_reversed = (
+ ICON_PAUSED if self.status == 'playing' else
+ ICON_PLAYING
+ )
+
+ def _print(self, status):
+ self.__print(status, self)
+
+ def _parseMetadata(self):
+ if self._metadata != None:
+ # Obtain properties from _metadata
+ _artist = _getProperty(self._metadata, 'xesam:artist', [''])
+ _album = _getProperty(self._metadata, 'xesam:album', '')
+ _title = _getProperty(self._metadata, 'xesam:title', '')
+ _track = _getProperty(self._metadata, 'xesam:trackNumber', '')
+ _genre = _getProperty(self._metadata, 'xesam:genre', [''])
+ _disc = _getProperty(self._metadata, 'xesam:discNumber', '')
+ _length = _getProperty(self._metadata, 'xesam:length', 0) or _getProperty(self._metadata, 'mpris:length', 0)
+ _length_int = _length if type(_length) is int else int(float(_length))
+ _fmt_length = ( # Formats using h:mm:ss if length > 1 hour, else m:ss
+ f'{_length_int/1e6//60:.0f}:{_length_int/1e6%60:02.0f}'
+ if _length_int < 3600*1e6 else
+ f'{_length_int/1e6//3600:.0f}:{_length_int/1e6%3600//60:02.0f}:{_length_int/1e6%60:02.0f}'
+ )
+ _date = _getProperty(self._metadata, 'xesam:contentCreated', '')
+ _year = _date[0:4] if len(_date) else ''
+ _url = _getProperty(self._metadata, 'xesam:url', '')
+ _cover = _getProperty(self._metadata, 'xesam:artUrl', '') or _getProperty(self._metadata, 'mpris:artUrl', '')
+ _duration = _getDuration(_length_int)
+ # Update metadata
+ self.metadata['artist'] = re.sub(SAFE_TAG_REGEX, """\1\1""", _metadataGetFirstItem(_artist))
+ self.metadata['album'] = re.sub(SAFE_TAG_REGEX, """\1\1""", _metadataGetFirstItem(_album))
+ self.metadata['title'] = re.sub(SAFE_TAG_REGEX, """\1\1""", _metadataGetFirstItem(_title))
+ self.metadata['track'] = _track
+ self.metadata['genre'] = re.sub(SAFE_TAG_REGEX, """\1\1""", _metadataGetFirstItem(_genre))
+ self.metadata['disc'] = _disc
+ self.metadata['date'] = re.sub(SAFE_TAG_REGEX, """\1\1""", _date)
+ self.metadata['year'] = re.sub(SAFE_TAG_REGEX, """\1\1""", _year)
+ self.metadata['url'] = _url
+ self.metadata['filename'] = os.path.basename(_url)
+ self.metadata['length'] = _length_int
+ self.metadata['fmt-length'] = _fmt_length
+ self.metadata['cover'] = re.sub(SAFE_TAG_REGEX, """\1\1""", _metadataGetFirstItem(_cover))
+ self.metadata['duration'] = _duration
+
+ def onMetadataChanged(self, track_id, metadata):
+ self.refreshMetadata()
+ self.printStatus()
+
+ def onPropertiesChanged(self, interface, properties, signature):
+ updated = False
+ if dbus.String('Metadata') in properties:
+ _metadata = properties[dbus.String('Metadata')]
+ if _metadata != self._metadata:
+ self._metadata = _metadata
+ self._parseMetadata()
+ updated = True
+ if dbus.String('PlaybackStatus') in properties:
+ status = str(properties[dbus.String('PlaybackStatus')]).lower()
+ if status != self.status:
+ self.status = status
+ self.checkPositionTimer()
+ self.updateIcon()
+ updated = True
+ if dbus.String('Rate') in properties and dbus.String('PlaybackStatus') not in properties:
+ self.refreshStatus()
+ if NEEDS_POSITION and dbus.String('Rate') in properties:
+ rate = properties[dbus.String('Rate')]
+ if rate != self._rate:
+ self._rate = rate
+ self.refreshPosition()
+
+ if updated:
+ self.refreshPosition()
+ self.printStatus()
+
+ def checkPositionTimer(self):
+ if NEEDS_POSITION and self.status == 'playing' and not self._positionTimerRunning:
+ self._positionTimerRunning = True
+ GLib.timeout_add_seconds(1, self._positionTimer)
+
+ def onSeeked(self, position):
+ self.refreshPosition()
+ self.printStatus()
+
+ def _positionTimer(self):
+ self.printStatus()
+ self._positionTimerRunning = self.status == 'playing'
+ return self._positionTimerRunning
+
+ def refreshPosition(self):
+ try:
+ time_us = self._getProperty('org.mpris.MediaPlayer2.Player', 'Position')
+ except dbus.exceptions.DBusException:
+ time_us = 0
+
+ self._timeAtLastUpdate = time.time()
+ self._positionAtLastUpdate = time_us / 1000000
+
+ def _getPosition(self):
+ if self.status == 'playing':
+ return self._positionAtLastUpdate + self._rate * (time.time() - self._timeAtLastUpdate)
+ else:
+ return self._positionAtLastUpdate
+
+ def _statusReplace(self, match, metadata):
+ tag = match.group('tag')
+ format = match.group('format')
+ formatlen = match.group('formatlen')
+ text = match.group('text')
+ tag_found = False
+ reversed_tag = False
+
+ if tag.startswith('-'):
+ tag = tag[1:]
+ reversed_tag = True
+
+ if format is None:
+ tag_is_format_match = re.match(FORMAT_TAG_REGEX, tag)
+ if tag_is_format_match:
+ format = tag_is_format_match.group('format')
+ formatlen = tag_is_format_match.group('formatlen')
+ tag_found = True
+ if format is not None:
+ text = text.format_map(CleanSafeDict(**metadata))
+ if format == 'w':
+ formatlen = int(formatlen)
+ text = text[:formatlen]
+ elif format == 't':
+ formatlen = int(formatlen)
+ if len(text) > formatlen:
+ text = text[:max(formatlen - len(TRUNCATE_STRING), 0)] + TRUNCATE_STRING
+ if tag_found is False and tag in metadata and len(metadata[tag]):
+ tag_found = True
+
+ if reversed_tag:
+ tag_found = not tag_found
+
+ if tag_found:
+ return text
+ else:
+ return ''
+
+ def printStatus(self):
+ if self.status in [ 'playing', 'paused' ]:
+ metadata = { **self.metadata, 'icon': self.icon, 'icon-reversed': self.icon_reversed }
+ if NEEDS_POSITION:
+ metadata['position'] = time.strftime("%M:%S", time.gmtime(self._getPosition()))
+ # replace metadata tags in text
+ text = re.sub(FORMAT_REGEX, lambda match: self._statusReplace(match, metadata), FORMAT_STRING)
+ # restore polybar tag formatting and replace any remaining metadata tags after that
+ try:
+ text = re.sub(r'p(.*?)p(.*?)p(.*?)p', r'%{\1}\2%{\3}', text.format_map(CleanSafeDict(**metadata)))
+ except:
+ print("Invalid format string")
+ self._print(text)
+ else:
+ self._print(ICON_STOPPED)
+
+
+def _dbusValueToPython(value):
+ if isinstance(value, dbus.Dictionary):
+ return {_dbusValueToPython(key): _dbusValueToPython(value) for key, value in value.items()}
+ elif isinstance(value, dbus.Array):
+ return [ _dbusValueToPython(item) for item in value ]
+ elif isinstance(value, dbus.Boolean):
+ return int(value) == 1
+ elif (
+ isinstance(value, dbus.Byte) or
+ isinstance(value, dbus.Int16) or
+ isinstance(value, dbus.UInt16) or
+ isinstance(value, dbus.Int32) or
+ isinstance(value, dbus.UInt32) or
+ isinstance(value, dbus.Int64) or
+ isinstance(value, dbus.UInt64)
+ ):
+ return int(value)
+ elif isinstance(value, dbus.Double):
+ return float(value)
+ elif (
+ isinstance(value, dbus.ObjectPath) or
+ isinstance(value, dbus.Signature) or
+ isinstance(value, dbus.String)
+ ):
+ return unquote(str(value))
+
+def _getProperty(properties, property, default = None):
+ value = default
+ if not isinstance(property, dbus.String):
+ property = dbus.String(property)
+ if property in properties:
+ value = properties[property]
+ return _dbusValueToPython(value)
+ else:
+ return value
+
+def _getDuration(t: int):
+ seconds = t / 1000000
+ return time.strftime("%M:%S", time.gmtime(seconds))
+
+def _metadataGetFirstItem(_value):
+ if type(_value) is list:
+ # Returns the string representation of the first item on _value if it has at least one item.
+ # Returns an empty string if _value is empty.
+ return str(_value[0]) if len(_value) else ''
+ else:
+ # If _value isn't a list just return the string representation of _value.
+ return str(_value)
+
+class CleanSafeDict(dict):
+ def __missing__(self, key):
+ return '{{{}}}'.format(key)
+
+
+"""
+Seems to assure print() actually prints when no terminal is connected
+"""
+
+_last_status = ''
+def _printFlush(status, **kwargs):
+ global _last_status
+ if status != _last_status:
+ print(status, **kwargs)
+ sys.stdout.flush()
+ _last_status = status
+
+
+
+parser = argparse.ArgumentParser()
+parser.add_argument('command', help="send the given command to the active player",
+ choices=[ 'play', 'pause', 'play-pause', 'stop', 'previous', 'next', 'status', 'list', 'current', 'metadata', 'raise' ],
+ default=None,
+ nargs='?')
+parser.add_argument('-b', '--blacklist', help="ignore a player by it's bus name. Can be given multiple times (e.g. -b vlc -b audacious)",
+ action='append',
+ metavar="BUS_NAME",
+ default=[])
+parser.add_argument('-w', '--whitelist', help="permit a player by it's bus name like --blacklist. will block --blacklist if given",
+ action='append',
+ metavar="BUS_NAME",
+ default=[])
+parser.add_argument('-f', '--format', default='{icon} {:artist:{artist} - :}{:title:{title}:}{:-title:{filename}:}')
+parser.add_argument('--truncate-text', default='…')
+parser.add_argument('--icon-playing', default='⏵')
+parser.add_argument('--icon-paused', default='⏸')
+parser.add_argument('--icon-stopped', default='⏹')
+parser.add_argument('--icon-none', default='')
+args = parser.parse_args()
+
+FORMAT_STRING = re.sub(r'%\{(.*?)\}(.*?)%\{(.*?)\}', r'p\1p\2p\3p', args.format)
+NEEDS_POSITION = "{position}" in FORMAT_STRING
+
+TRUNCATE_STRING = args.truncate_text
+ICON_PLAYING = args.icon_playing
+ICON_PAUSED = args.icon_paused
+ICON_STOPPED = args.icon_stopped
+ICON_NONE = args.icon_none
+
+block_mode = len(args.whitelist) == 0
+filter_list = args.blacklist if block_mode else args.whitelist
+
+if args.command is None:
+ PlayerManager(filter_list = filter_list, block_mode = block_mode)
+else:
+ player_manager = PlayerManager(filter_list = filter_list, block_mode = block_mode, connect = False)
+ current_player = player_manager.getCurrentPlayer()
+ if args.command == 'play' and current_player:
+ current_player.play()
+ elif args.command == 'pause' and current_player:
+ current_player.pause()
+ elif args.command == 'play-pause' and current_player:
+ current_player.playpause()
+ elif args.command == 'stop' and current_player:
+ current_player.stop()
+ elif args.command == 'previous' and current_player:
+ current_player.previous()
+ elif args.command == 'next' and current_player:
+ current_player.next()
+ elif args.command == 'status' and current_player:
+ current_player.printStatus()
+ elif args.command == 'list':
+ print("\n".join(sorted([
+ "{} : {}".format(player.bus_name.split('.')[3], player.status)
+ for player in player_manager.players.values() ])))
+ elif args.command == 'current' and current_player:
+ print("{} : {}".format(current_player.bus_name.split('.')[3], current_player.status))
+ elif args.command == 'metadata' and current_player:
+ print(_dbusValueToPython(current_player._metadata))
+ elif args.command == 'raise' and current_player:
+ current_player.raisePlayer()
diff --git a/.config/polybar/scripts/player-mpris-tail/screenshots/1.png b/.config/polybar/scripts/player-mpris-tail/screenshots/1.png
new file mode 100644
index 0000000..686c7d6
Binary files /dev/null and b/.config/polybar/scripts/player-mpris-tail/screenshots/1.png differ
diff --git a/.config/polybar/scripts/player-mpris-tail/screenshots/2.png b/.config/polybar/scripts/player-mpris-tail/screenshots/2.png
new file mode 100644
index 0000000..7aeabf3
Binary files /dev/null and b/.config/polybar/scripts/player-mpris-tail/screenshots/2.png differ
diff --git a/.config/polybar/scripts/polybar-redshift/env.sh b/.config/polybar/scripts/polybar-redshift/env.sh
new file mode 100644
index 0000000..26e38c5
--- /dev/null
+++ b/.config/polybar/scripts/polybar-redshift/env.sh
@@ -0,0 +1,3 @@
+
+export REDSHIFT=on
+export REDSHIFT_TEMP=5600
diff --git a/.config/polybar/scripts/polybar-redshift/redshift.sh b/.config/polybar/scripts/polybar-redshift/redshift.sh
new file mode 100755
index 0000000..cedc674
--- /dev/null
+++ b/.config/polybar/scripts/polybar-redshift/redshift.sh
@@ -0,0 +1,47 @@
+#!/bin/sh
+
+envFile=~/.config/polybar/scripts/env.sh
+changeValue=300
+
+changeMode() {
+ sed -i "s/REDSHIFT=$1/REDSHIFT=$2/g" $envFile
+ REDSHIFT=$2
+ echo $REDSHIFT
+}
+
+changeTemp() {
+ if [ "$2" -gt 1000 ] && [ "$2" -lt 25000 ]
+ then
+ sed -i "s/REDSHIFT_TEMP=$1/REDSHIFT_TEMP=$2/g" $envFile
+ redshift -P -O $((REDSHIFT_TEMP+changeValue))
+ fi
+}
+
+case $1 in
+ toggle)
+ if [ "$REDSHIFT" = on ];
+ then
+ changeMode "$REDSHIFT" off
+ redshift -x
+ else
+ changeMode "$REDSHIFT" on
+ redshift -O "$REDSHIFT_TEMP"
+ fi
+ ;;
+ increase)
+ changeTemp $((REDSHIFT_TEMP)) $((REDSHIFT_TEMP+changeValue))
+ ;;
+ decrease)
+ changeTemp $((REDSHIFT_TEMP)) $((REDSHIFT_TEMP-changeValue));
+ ;;
+ temperature)
+ case $REDSHIFT in
+ on)
+ printf "%dK" "$REDSHIFT_TEMP"
+ ;;
+ off)
+ printf "off"
+ ;;
+ esac
+ ;;
+esac
diff --git a/.config/polybar/scripts/popup-calendar/README.md b/.config/polybar/scripts/popup-calendar/README.md
new file mode 100644
index 0000000..8ed4be3
--- /dev/null
+++ b/.config/polybar/scripts/popup-calendar/README.md
@@ -0,0 +1,41 @@
+# Script: popup-calendar
+
+A small script that displays the date and opens a small popup calendar with YAD when clicked.
+
+
+
+
+## Dependencies
+
+* [`yad`](https://sourceforge.net/projects/yad-dialog/)
+* `xdotool`
+
+
+## Configuration
+
+Change these values if you want:
+
+```sh
+BAR_HEIGHT=22
+BORDER_SIZE=1
+YAD_WIDTH=222
+YAD_HEIGHT=188
+DATE="$(date +"%a %d %H:%M")"
+```
+
+If you use a tiling window manager you should enable floating for `yad-calendar`. This example is for `i3wm`:
+
+```ini
+for_window [class="Yad" title="yad-calendar"] floating enable
+```
+
+
+## Module
+
+```ini
+[module/popup-calendar]
+type = custom/script
+exec = ~/polybar-scripts/popup-calendar.sh
+interval = 5
+click-left = ~/polybar-scripts/popup-calendar.sh --popup &
+```
diff --git a/.config/polybar/scripts/popup-calendar/popup-calendar.sh b/.config/polybar/scripts/popup-calendar/popup-calendar.sh
new file mode 100644
index 0000000..7f3540e
--- /dev/null
+++ b/.config/polybar/scripts/popup-calendar/popup-calendar.sh
@@ -0,0 +1,41 @@
+#!/bin/sh
+
+BAR_HEIGHT=22 # polybar height
+BORDER_SIZE=1 # border size from your wm settings
+YAD_WIDTH=222 # 222 is minimum possible value
+YAD_HEIGHT=193 # 193 is minimum possible value
+DATE="$(date +"%a %d %H:%M")"
+
+case "$1" in
+--popup)
+ if [ "$(xdotool getwindowfocus getwindowname)" = "yad-calendar" ]; then
+ exit 0
+ fi
+
+ eval "$(xdotool getmouselocation --shell)"
+ eval "$(xdotool getdisplaygeometry --shell)"
+
+ # X
+ if [ "$((X + YAD_WIDTH / 2 + BORDER_SIZE))" -gt "$WIDTH" ]; then #Right side
+ : $((pos_x = WIDTH - YAD_WIDTH - BORDER_SIZE))
+ elif [ "$((X - YAD_WIDTH / 2 - BORDER_SIZE))" -lt 0 ]; then #Left side
+ : $((pos_x = BORDER_SIZE))
+ else #Center
+ : $((pos_x = X - YAD_WIDTH / 2))
+ fi
+
+ # Y
+ if [ "$Y" -gt "$((HEIGHT / 2))" ]; then #Bottom
+ : $((pos_y = HEIGHT - YAD_HEIGHT - BAR_HEIGHT - BORDER_SIZE))
+ else #Top
+ : $((pos_y = BAR_HEIGHT + BORDER_SIZE))
+ fi
+
+ yad --calendar --undecorated --fixed --close-on-unfocus --no-buttons \
+ --width="$YAD_WIDTH" --height="$YAD_HEIGHT" --posx="$pos_x" --posy="$pos_y" \
+ --title="yad-calendar" --borders=0 >/dev/null &
+ ;;
+*)
+ echo "$DATE"
+ ;;
+esac
diff --git a/.config/polybar/scripts/popup-calendar/screenshots/1.png b/.config/polybar/scripts/popup-calendar/screenshots/1.png
new file mode 100644
index 0000000..da34d8e
Binary files /dev/null and b/.config/polybar/scripts/popup-calendar/screenshots/1.png differ
diff --git a/.config/polybar/scripts/popup-powermenu/README.md b/.config/polybar/scripts/popup-powermenu/README.md
new file mode 100644
index 0000000..57c4ad4
--- /dev/null
+++ b/.config/polybar/scripts/popup-powermenu/README.md
@@ -0,0 +1,19 @@
+# Script: popup-powermenu
+
+A popup menu made with Yad that provides a window giving options to shutdown, reboot, logout.
+
+
+## Dependencies
+
+* [`yad`](https://sourceforge.net/projects/yad-dialog/)
+
+
+## Module
+
+```ini
+[module/popup-powermenu]
+type = custom/script
+exec = ~/polybar-scripts/popup-powermenu.sh
+interval = 5
+click-left = ~/polybar-scripts/popup-powermenu.sh --popup &
+```
diff --git a/.config/polybar/scripts/popup-powermenu/popup-powermenu.sh b/.config/polybar/scripts/popup-powermenu/popup-powermenu.sh
new file mode 100644
index 0000000..32fa4d5
--- /dev/null
+++ b/.config/polybar/scripts/popup-powermenu/popup-powermenu.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+case "$1" in
+ --popup)
+ yad=$(yad --width 300 --entry --undecorated --title "System Logout" --image=gnome-shutdown --text "Choose action:" --entry-text "Shutdown" "Reboot" "Logout" "Suspend")
+
+ case "$yad" in
+ Shutdown)
+ poweroff
+ ;;
+ Reboot)
+ reboot
+ ;;
+ Suspend)
+ hibernate
+ ;;
+ Logout)
+ bspc quit
+ ;;
+ esac
+ ;;
+ *)
+ echo "#1"
+ ;;
+esac
diff --git a/.config/polybar/scripts/pulseaudio-microphone/README.md b/.config/polybar/scripts/pulseaudio-microphone/README.md
new file mode 100644
index 0000000..2c7a207
--- /dev/null
+++ b/.config/polybar/scripts/pulseaudio-microphone/README.md
@@ -0,0 +1,17 @@
+# Script: pulseaudio-microphone
+
+A script that shows if the PulseAudio default source (microphone) is muted or not.
+
+Use left click to toggle the state.
+
+## Module
+
+```ini
+[module/pulseaudio-microphone]
+type = custom/script
+exec = ~/polybar-scripts/pulseaudio-microphone.sh
+tail = true
+click-left = ~/polybar-scripts/pulseaudio-microphone.sh --toggle &
+scroll-up = ~/polybar-scripts/pulseaudio-microphone.sh --increase &
+scroll-down = ~/polybar-scripts/pulseaudio-microphone.sh --decrease &
+```
diff --git a/.config/polybar/scripts/pulseaudio-microphone/pulseaudio-microphone.sh b/.config/polybar/scripts/pulseaudio-microphone/pulseaudio-microphone.sh
new file mode 100644
index 0000000..0faf6e7
--- /dev/null
+++ b/.config/polybar/scripts/pulseaudio-microphone/pulseaudio-microphone.sh
@@ -0,0 +1,57 @@
+#!/bin/sh
+
+status() {
+ MUTED=$(pacmd list-sources | awk '/\*/,EOF {print}' | awk '/muted/ {print $2; exit}')
+
+ if [ "$MUTED" = "yes" ]; then
+ echo "muted"
+ else
+ pacmd list-sources | grep "\* index:" -A 7 | grep volume | awk -F/ '{print $2}' | tr -d ' '
+ fi
+}
+
+listen() {
+ status
+
+ LANG=EN; pactl subscribe | while read -r event; do
+ if echo "$event" | grep -q "source" || echo "$event" | grep -q "server"; then
+ status
+ fi
+ done
+}
+
+toggle() {
+ MUTED=$(pacmd list-sources | awk '/\*/,EOF {print}' | awk '/muted/ {print $2; exit}')
+ DEFAULT_SOURCE=$(pacmd list-sources | awk '/\*/,EOF {print $3; exit}')
+
+ if [ "$MUTED" = "yes" ]; then
+ pactl set-source-mute "$DEFAULT_SOURCE" 0
+ else
+ pactl set-source-mute "$DEFAULT_SOURCE" 1
+ fi
+}
+
+increase() {
+ DEFAULT_SOURCE=$(pacmd list-sources | awk '/\*/,EOF {print $3; exit}')
+ pactl set-source-volume "$DEFAULT_SOURCE" +5%
+}
+
+decrease() {
+ DEFAULT_SOURCE=$(pacmd list-sources | awk '/\*/,EOF {print $3; exit}')
+ pactl set-source-volume "$DEFAULT_SOURCE" -5%
+}
+
+case "$1" in
+ --toggle)
+ toggle
+ ;;
+ --increase)
+ increase
+ ;;
+ --decrease)
+ decrease
+ ;;
+ *)
+ listen
+ ;;
+esac
diff --git a/.config/polybar/scripts/pulseaudio-simple/README.md b/.config/polybar/scripts/pulseaudio-simple/README.md
new file mode 100644
index 0000000..7fb7521
--- /dev/null
+++ b/.config/polybar/scripts/pulseaudio-simple/README.md
@@ -0,0 +1,18 @@
+# Script: pulseaudio-simple
+
+A script that shows the PulseAudio volume.
+
+
+## Dependencies
+
+* `pamixer`
+
+
+## Module
+
+```ini
+[module/pulseaudio-simple]
+type = custom/script
+exec = ~/polybar-scripts/pulseaudio-simple.sh
+interval = 3
+```
diff --git a/.config/polybar/scripts/pulseaudio-simple/pulseaudio-simple.sh b/.config/polybar/scripts/pulseaudio-simple/pulseaudio-simple.sh
new file mode 100644
index 0000000..0b7ff41
--- /dev/null
+++ b/.config/polybar/scripts/pulseaudio-simple/pulseaudio-simple.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+muted=$(pamixer --sink 0 --get-mute)
+
+if [ "$muted" = true ]; then
+ echo "#1 --"
+else
+ volume=$(pamixer --sink 0 --get-volume)
+
+ if [ "$volume" -gt 49 ]; then
+ echo "#2 $volume %"
+ else
+ echo "#3 $volume %"
+ fi
+fi
diff --git a/.config/polybar/scripts/pulseaudio-tail/README.md b/.config/polybar/scripts/pulseaudio-tail/README.md
new file mode 100644
index 0000000..1b49318
--- /dev/null
+++ b/.config/polybar/scripts/pulseaudio-tail/README.md
@@ -0,0 +1,26 @@
+# Script: pulseaudio-tail
+
+A script to control PulseAudio.
+
+The script uses polybar's tail function to display the adjustments in real time. Please note that there is already a polybar module [`pulseaudio`](https://github.com/jaagr/polybar/wiki/Module:-pulseaudio) for this task.
+
+
+## Dependencies
+
+* `pamixer`
+
+Maybe `pavucontrol` is a good idea. In the example it is opened with a right mouse click.
+
+
+## Module
+
+```ini
+[module/pulseaudio-tail]
+type = custom/script
+exec = ~/polybar-scripts/pulseaudio-tail.sh
+tail = true
+click-right = exec pavucontrol &
+click-left = ~/polybar-scripts/pulseaudio-tail.sh --mute &
+scroll-up = ~/polybar-scripts/pulseaudio-tail.sh --up &
+scroll-down = ~/polybar-scripts/pulseaudio-tail.sh --down &
+```
diff --git a/.config/polybar/scripts/pulseaudio-tail/pulseaudio-tail.sh b/.config/polybar/scripts/pulseaudio-tail/pulseaudio-tail.sh
new file mode 100644
index 0000000..862b8c2
--- /dev/null
+++ b/.config/polybar/scripts/pulseaudio-tail/pulseaudio-tail.sh
@@ -0,0 +1,66 @@
+#!/bin/sh
+
+update_sink() {
+ sink=$(pacmd list-sinks | sed -n '/\* index:/ s/.*: //p')
+}
+
+volume_up() {
+ update_sink
+ pactl set-sink-volume "$sink" +1%
+}
+
+volume_down() {
+ update_sink
+ pactl set-sink-volume "$sink" -1%
+}
+
+volume_mute() {
+ update_sink
+ pactl set-sink-mute "$sink" toggle
+}
+
+volume_print() {
+ update_sink
+
+ active_port=$(pacmd list-sinks | sed -n "/index: $sink/,/index:/p" | grep active)
+ if echo "$active_port" | grep -q speaker; then
+ icon="#1"
+ elif echo "$active_port" | grep -q headphones; then
+ icon="#2"
+ else
+ icon="#3"
+ fi
+
+ muted=$(pamixer --sink "$sink" --get-mute)
+
+ if [ "$muted" = true ]; then
+ echo "$icon --"
+ else
+ echo "$icon $(pamixer --sink "$sink" --get-volume)"
+ fi
+}
+
+listen() {
+ volume_print
+
+ pactl subscribe | while read -r event; do
+ if echo "$event" | grep -qv "Client"; then
+ volume_print
+ fi
+ done
+}
+
+case "$1" in
+ --up)
+ volume_up
+ ;;
+ --down)
+ volume_down
+ ;;
+ --mute)
+ volume_mute
+ ;;
+ *)
+ listen
+ ;;
+esac
diff --git a/.config/polybar/scripts/system-ati-radeontop/README.md b/.config/polybar/scripts/system-ati-radeontop/README.md
new file mode 100644
index 0000000..783e1c7
--- /dev/null
+++ b/.config/polybar/scripts/system-ati-radeontop/README.md
@@ -0,0 +1,21 @@
+# Script: system-ati-radeontop
+
+A script that outputs gpu usage for amd cards using radeontop.
+
+
+
+
+## Dependencies
+
+* [`radeontop`](https://github.com/clbr/radeontop)
+
+
+## Module
+
+```ini
+[module/system-ati-radeontop]
+type = custom/script
+exec = ~/polybar-scripts/system-ati-radeontop.sh
+tail = true
+format="%"
+```
diff --git a/.config/polybar/scripts/system-ati-radeontop/screenshots/1.png b/.config/polybar/scripts/system-ati-radeontop/screenshots/1.png
new file mode 100644
index 0000000..bd1281a
Binary files /dev/null and b/.config/polybar/scripts/system-ati-radeontop/screenshots/1.png differ
diff --git a/.config/polybar/scripts/system-ati-radeontop/system-ati-radeontop.sh b/.config/polybar/scripts/system-ati-radeontop/system-ati-radeontop.sh
new file mode 100644
index 0000000..0126577
--- /dev/null
+++ b/.config/polybar/scripts/system-ati-radeontop/system-ati-radeontop.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+radeontop -d - -i 1 | grep --line-buffered -oP "gpu \K\d{1,3}"
diff --git a/.config/polybar/scripts/system-bluetooth-bluetoothctl/README.md b/.config/polybar/scripts/system-bluetooth-bluetoothctl/README.md
new file mode 100644
index 0000000..c0bf5ba
--- /dev/null
+++ b/.config/polybar/scripts/system-bluetooth-bluetoothctl/README.md
@@ -0,0 +1,30 @@
+# Script: system-bluetooth-bluetoothctl
+
+A shell script which displays the status of bluetooth and the paired devices.
+
+Use the toggle option to power on the controller and try to connect to all paired devices or to disconnect all connections and turn off the controller.
+
+
+
+
+## Dependencies
+
+* `bluetoothctl`
+
+
+## Configuration
+
+Use the `set-alias` feature of `bluetoothctl` to customize your device names.
+
+To enable battery level detection set `Experimental = true` in `/etc/bluetooth/main.conf`.
+
+
+## Module
+
+```ini
+[module/system-bluetooth-bluetoothctl]
+type = custom/script
+exec = ~/polybar-scripts/system-bluetooth-bluetoothctl.sh
+tail = true
+click-left = ~/polybar-scripts/system-bluetooth-bluetoothctl.sh --toggle &
+```
diff --git a/.config/polybar/scripts/system-bluetooth-bluetoothctl/screenshots/1.png b/.config/polybar/scripts/system-bluetooth-bluetoothctl/screenshots/1.png
new file mode 100644
index 0000000..cbdb776
Binary files /dev/null and b/.config/polybar/scripts/system-bluetooth-bluetoothctl/screenshots/1.png differ
diff --git a/.config/polybar/scripts/system-bluetooth-bluetoothctl/system-bluetooth-bluetoothctl.sh b/.config/polybar/scripts/system-bluetooth-bluetoothctl/system-bluetooth-bluetoothctl.sh
new file mode 100644
index 0000000..de5d97d
--- /dev/null
+++ b/.config/polybar/scripts/system-bluetooth-bluetoothctl/system-bluetooth-bluetoothctl.sh
@@ -0,0 +1,77 @@
+#!/bin/sh
+
+bluetooth_print() {
+ bluetoothctl | grep --line-buffered 'Device\|#' | while read -r REPLY; do
+ if [ "$(systemctl is-active "bluetooth.service")" = "active" ]; then
+ printf '#1'
+
+ devices_paired=$(bluetoothctl devices Paired | grep Device | cut -d ' ' -f 2)
+ counter=0
+
+ for device in $devices_paired; do
+ device_info=$(bluetoothctl info "$device")
+
+ if echo "$device_info" | grep -q "Connected: yes"; then
+ device_output=$(echo "$device_info" | grep "Alias" | cut -d ' ' -f 2-)
+ device_battery_percent=$(echo "$device_info" | grep "Battery Percentage" | awk -F'[()]' '{print $2}')
+
+ if [ -n "$device_battery_percent" ]; then
+ if [ "$device_battery_percent" -gt 90 ]; then
+ device_battery_icon="#25"
+ elif [ "$device_battery_percent" -gt 60 ]; then
+ device_battery_icon="#24"
+ elif [ "$device_battery_percent" -gt 35 ]; then
+ device_battery_icon="#23"
+ elif [ "$device_battery_percent" -gt 10 ]; then
+ device_battery_icon="#22"
+ else
+ device_battery_icon="#21"
+ fi
+
+ device_output="$device_output $device_battery_icon $device_battery_percent%"
+ fi
+
+ if [ $counter -gt 0 ]; then
+ printf ", %s" "$device_output"
+ else
+ printf " %s" "$device_output"
+ fi
+
+ counter=$((counter + 1))
+ fi
+ done
+
+ printf '\n'
+ else
+ echo "#2"
+ fi
+ done
+}
+
+bluetooth_toggle() {
+ if bluetoothctl show | grep -q "Powered: no"; then
+ bluetoothctl power on >> /dev/null
+ sleep 1
+
+ devices_paired=$(bluetoothctl devices Paired | grep Device | cut -d ' ' -f 2)
+ echo "$devices_paired" | while read -r line; do
+ bluetoothctl connect "$line" >> /dev/null
+ done
+ else
+ devices_paired=$(bluetoothctl devices Paired | grep Device | cut -d ' ' -f 2)
+ echo "$devices_paired" | while read -r line; do
+ bluetoothctl disconnect "$line" >> /dev/null
+ done
+
+ bluetoothctl power off >> /dev/null
+ fi
+}
+
+case "$1" in
+ --toggle)
+ bluetooth_toggle
+ ;;
+ *)
+ bluetooth_print
+ ;;
+esac
diff --git a/.config/polybar/scripts/system-cpu-frequency/README.md b/.config/polybar/scripts/system-cpu-frequency/README.md
new file mode 100644
index 0000000..5db5163
--- /dev/null
+++ b/.config/polybar/scripts/system-cpu-frequency/README.md
@@ -0,0 +1,13 @@
+# Script: system-cpu-frequency
+
+A shell script that shows the average core frequency (average over number, not over time) in GHz.
+
+
+## Module
+
+```ini
+[module/system-cpu-frequency]
+type = custom/script
+exec = ~/polybar-scripts/system-cpu-frequency.sh
+interval = 10
+```
diff --git a/.config/polybar/scripts/system-cpu-frequency/system-cpu-frequency.sh b/.config/polybar/scripts/system-cpu-frequency/system-cpu-frequency.sh
new file mode 100644
index 0000000..dddb858
--- /dev/null
+++ b/.config/polybar/scripts/system-cpu-frequency/system-cpu-frequency.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+c=0;t=0
+
+awk '/MHz/ {print $4}' < /proc/cpuinfo | (while read -r i
+do
+ t=$( echo "$t + $i" | bc )
+ c=$((c+1))
+done
+echo "scale=2; $t / $c / 1000" | bc | awk '{print $1" GHz"}')
diff --git a/.config/polybar/scripts/system-cpu-loadavg/README.md b/.config/polybar/scripts/system-cpu-loadavg/README.md
new file mode 100644
index 0000000..0ff65ce
--- /dev/null
+++ b/.config/polybar/scripts/system-cpu-loadavg/README.md
@@ -0,0 +1,13 @@
+# Script: system-cpu-loadavg
+
+A shell script which displays the cpu loadavg. It is a simple script. Very simple.
+
+
+## Module
+
+```ini
+[module/system-cpu-loadavg]
+type = custom/script
+exec = ~/polybar-scripts/system-cpu-loadavg.sh
+interval = 5
+```
diff --git a/.config/polybar/scripts/system-cpu-loadavg/system-cpu-loadavg.sh b/.config/polybar/scripts/system-cpu-loadavg/system-cpu-loadavg.sh
new file mode 100644
index 0000000..c96bf78
--- /dev/null
+++ b/.config/polybar/scripts/system-cpu-loadavg/system-cpu-loadavg.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+awk '{print $1" "$2" "$3}' < /proc/loadavg
diff --git a/.config/polybar/scripts/system-cpu-temppercore/README.md b/.config/polybar/scripts/system-cpu-temppercore/README.md
new file mode 100644
index 0000000..0ddc941
--- /dev/null
+++ b/.config/polybar/scripts/system-cpu-temppercore/README.md
@@ -0,0 +1,20 @@
+# Script: system-cpu-temppercore
+
+A script that displays the temperature for each core.
+
+
+
+
+## Dependencies
+
+* `lm_sensors`
+
+
+## Module
+
+```ini
+[module/system-cpu-temppercore]
+type = custom/script
+exec = ~/polybar-scripts/system-cpu-temppercore.sh
+interval = 60
+```
diff --git a/.config/polybar/scripts/system-cpu-temppercore/screenshots/1.png b/.config/polybar/scripts/system-cpu-temppercore/screenshots/1.png
new file mode 100644
index 0000000..f8e6712
Binary files /dev/null and b/.config/polybar/scripts/system-cpu-temppercore/screenshots/1.png differ
diff --git a/.config/polybar/scripts/system-cpu-temppercore/system-cpu-temppercore.sh b/.config/polybar/scripts/system-cpu-temppercore/system-cpu-temppercore.sh
new file mode 100644
index 0000000..1ebc3b2
--- /dev/null
+++ b/.config/polybar/scripts/system-cpu-temppercore/system-cpu-temppercore.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+sensors | grep Core | awk '{print substr($3, 2, length($3)-5)}' | tr "\\n" " " | sed 's/ /°C /g' | sed 's/ $//'
diff --git a/.config/polybar/scripts/system-eprivacy/README.md b/.config/polybar/scripts/system-eprivacy/README.md
new file mode 100644
index 0000000..4fdeb2a
--- /dev/null
+++ b/.config/polybar/scripts/system-eprivacy/README.md
@@ -0,0 +1,30 @@
+# Script: system-eprivacy
+
+A small script to manage the ePrivacy state for ThinkPads.
+
+
+
+
+## Dependencies
+
+* `inotify-tools`
+
+
+## Configuration
+
+You have to add the `/usr/bin/tee /proc/acpi/ibm/lcdshadow` command to the `/etc/sudoers` NOPASSWD of your user:
+
+```
+user ALL = NOPASSWD: /usr/bin/tee /proc/acpi/ibm/lcdshadow
+```
+
+
+## Module
+
+```ini
+[module/system-eprivacy]
+type = custom/script
+exec = ~/polybar-scripts/system-eprivacy.sh
+tail = true
+click-left = ~/polybar-scripts/system-eprivacy.sh --toggle &
+```
diff --git a/.config/polybar/scripts/system-eprivacy/screenshots/1.png b/.config/polybar/scripts/system-eprivacy/screenshots/1.png
new file mode 100644
index 0000000..36bd423
Binary files /dev/null and b/.config/polybar/scripts/system-eprivacy/screenshots/1.png differ
diff --git a/.config/polybar/scripts/system-eprivacy/system-eprivacy.sh b/.config/polybar/scripts/system-eprivacy/system-eprivacy.sh
new file mode 100644
index 0000000..6f9ac62
--- /dev/null
+++ b/.config/polybar/scripts/system-eprivacy/system-eprivacy.sh
@@ -0,0 +1,39 @@
+#!/bin/sh
+# shellcheck disable=SC2034
+
+eprivacy_status () {
+ grep status /proc/acpi/ibm/lcdshadow | awk '{ print $2 }'
+}
+
+eprivacy_print () {
+ if [ "$(eprivacy_status)" = 0 ]; then
+ echo "#1"
+ else
+ echo "#2"
+ fi
+}
+
+eprivacy_watch () {
+ eprivacy_print
+
+ inotifywait -q -m -e modify /proc/acpi/ibm/lcdshadow | while read -r "event" ; do
+ eprivacy_print
+ done
+}
+
+eprivacy_toggle () {
+ if [ "$(eprivacy_status)" = 0 ]; then
+ echo 1 | sudo tee /proc/acpi/ibm/lcdshadow > /dev/null
+ else
+ echo 0 | sudo tee /proc/acpi/ibm/lcdshadow > /dev/null
+ fi
+}
+
+case "$1" in
+ --toggle)
+ eprivacy_toggle
+ ;;
+ *)
+ eprivacy_watch
+ ;;
+esac
diff --git a/.config/polybar/scripts/system-fan-speed/README.md b/.config/polybar/scripts/system-fan-speed/README.md
new file mode 100644
index 0000000..2df8b7f
--- /dev/null
+++ b/.config/polybar/scripts/system-fan-speed/README.md
@@ -0,0 +1,19 @@
+# Script: system-fan-speed
+
+A shell script which displays the fan speed.
+
+
+## Dependencies
+
+* `lm_sensors`
+* `bc`
+
+
+## Module
+
+```ini
+[module/system-fan-speed]
+type = custom/script
+exec = ~/polybar-scripts/system-fan-speed.sh
+interval = 10
+```
diff --git a/.config/polybar/scripts/system-fan-speed/system-fan-speed.sh b/.config/polybar/scripts/system-fan-speed/system-fan-speed.sh
new file mode 100644
index 0000000..8a0f9da
--- /dev/null
+++ b/.config/polybar/scripts/system-fan-speed/system-fan-speed.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+speed=$(sensors | grep fan1 | awk '{print $2; exit}')
+
+if [ "$speed" != "" ]; then
+ speed_round=$(echo "$speed/1000" | bc -l | LANG=C xargs printf "%.1f\n")
+ echo "# $speed_round"
+else
+ echo "#"
+fi
diff --git a/.config/polybar/scripts/system-gpu-intel/README.md b/.config/polybar/scripts/system-gpu-intel/README.md
new file mode 100644
index 0000000..1a418a1
--- /dev/null
+++ b/.config/polybar/scripts/system-gpu-intel/README.md
@@ -0,0 +1,28 @@
+# Script: system-gpu-intel
+
+A script that shows the Intel GPU consumption. It is calculated on the current frequency.
+
+
+## Dependencies
+
+* `intel_gpu_frequency` from `intel-gpu-tools`
+* `bc`
+
+
+## Configuration
+
+You have to add the `intel_gpu_frequency` command to the `/etc/sudoers` NOPASSWD of your user:
+
+```
+user ALL=(ALL) NOPASSWD: /usr/bin/intel_gpu_frequency
+```
+
+
+## Module
+
+```ini
+[module/system-gpu-intel]
+type = custom/script
+exec = ~/polybar-scripts/system-gpu-intel.sh
+interval = 20
+```
diff --git a/.config/polybar/scripts/system-gpu-intel/system-gpu-intel.sh b/.config/polybar/scripts/system-gpu-intel/system-gpu-intel.sh
new file mode 100644
index 0000000..4a756a7
--- /dev/null
+++ b/.config/polybar/scripts/system-gpu-intel/system-gpu-intel.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+gpu=$(sudo intel_gpu_frequency --get)
+
+gpu_cur=$(echo "$gpu" | grep cur | awk '{ print $2 }')
+gpu_max=$(echo "$gpu" | grep max | awk '{ print $2 }')
+
+gpu_percent=$(echo "$gpu_cur/$gpu_max*100" | bc -l | cut -d "." -f 1)
+
+echo "# $gpu_percent %"
diff --git a/.config/polybar/scripts/system-gpu-optimus/README.md b/.config/polybar/scripts/system-gpu-optimus/README.md
new file mode 100644
index 0000000..e7f32f0
--- /dev/null
+++ b/.config/polybar/scripts/system-gpu-optimus/README.md
@@ -0,0 +1,25 @@
+# Script: system-gpu-optimus
+
+A script that shows the current GPU in use, given that the GPUs are managed by [optimus-manager](https://github.com/Askannz/optimus-manager).
+
+The script also allows for switching GPU in one click.
+Be aware that this will log you out of your session without asking for confirmation.
+
+
+
+
+## Configuration
+
+Set `hybrid_switching` to `1` if the system switches between hybrid and nvidia.
+Otherwise the system switches between intel and nvidia.
+
+
+## Module
+
+```ini
+[module/system-gpu-optimus]
+type = custom/script
+exec = ~/polybar-scripts/system-gpu-optimus.sh
+interval = 1200
+click-right = ~/polybar-scripts/system-gpu-optimus.sh --switch
+```
diff --git a/.config/polybar/scripts/system-gpu-optimus/screenshots/1.png b/.config/polybar/scripts/system-gpu-optimus/screenshots/1.png
new file mode 100644
index 0000000..101b5af
Binary files /dev/null and b/.config/polybar/scripts/system-gpu-optimus/screenshots/1.png differ
diff --git a/.config/polybar/scripts/system-gpu-optimus/system-gpu-optimus.sh b/.config/polybar/scripts/system-gpu-optimus/system-gpu-optimus.sh
new file mode 100644
index 0000000..f87b357
--- /dev/null
+++ b/.config/polybar/scripts/system-gpu-optimus/system-gpu-optimus.sh
@@ -0,0 +1,53 @@
+#!/bin/sh
+
+icon_intel="#1"
+icon_nvidia="#2"
+icon_hybrid="#3"
+
+hybrid_switching=0
+
+
+gpu_current() {
+ mode=$(optimus-manager --print-mode)
+
+ echo "$mode" | cut -d ' ' -f 5 | tr -d '[:space:]'
+}
+
+gpu_switch() {
+ mode=$(gpu_current)
+
+ if [ "$mode" = "intel" ]; then
+ next="nvidia"
+ elif [ "$mode" = "nvidia" ]; then
+ if [ "$hybrid_switching" = 1 ]; then
+ next="hybrid"
+ else
+ next="intel"
+ fi
+ elif [ "$mode" = "hybrid" ]; then
+ next="nvidia"
+ fi
+
+ optimus-manager --switch "$next" --no-confirm
+}
+
+gpu_display(){
+ mode=$(gpu_current)
+
+ if [ "$mode" = "intel" ]; then
+ echo "$icon_intel"
+ elif [ "$mode" = "nvidia" ]; then
+ echo "$icon_nvidia"
+ elif [ "$mode" = "hybrid" ]; then
+ echo "$icon_hybrid"
+ fi
+}
+
+case "$1" in
+ --switch)
+ gpu_switch
+ ;;
+ *)
+ gpu_display
+ ;;
+esac
diff --git a/.config/polybar/scripts/system-nvidia-bbswitch/README.md b/.config/polybar/scripts/system-nvidia-bbswitch/README.md
new file mode 100644
index 0000000..eb86e38
--- /dev/null
+++ b/.config/polybar/scripts/system-nvidia-bbswitch/README.md
@@ -0,0 +1,21 @@
+# Script: system-nvidia-bbswitch
+
+A shell script that shows if the NVIDIA card is used or not.
+
+This only will work for notebook users with a dedicated NVIDIA card and an Intel graphics card. Click the left mouse button to open the `nvidia-settings`.
+
+
+## Dependencies
+
+* [bbswitch](https://github.com/Bumblebee-Project/bbswitch): You will probably find `bbswitch` in the repository of your distribution.
+
+
+## Module
+
+```ini
+[module/system-nvidia-bbswitch]
+type = custom/script
+exec = ~/polybar-scripts/system-nvidia-bbswitch.sh
+interval = 5
+click-left = "optirun -b none nvidia-settings -c :8" &
+```
diff --git a/.config/polybar/scripts/system-nvidia-bbswitch/system-nvidia-bbswitch.sh b/.config/polybar/scripts/system-nvidia-bbswitch/system-nvidia-bbswitch.sh
new file mode 100644
index 0000000..9ec0974
--- /dev/null
+++ b/.config/polybar/scripts/system-nvidia-bbswitch/system-nvidia-bbswitch.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+if grep -q ON /proc/acpi/bbswitch; then
+ echo "# Active"
+else
+ echo "# Inactive"
+fi
diff --git a/.config/polybar/scripts/system-nvidia-smi/README.md b/.config/polybar/scripts/system-nvidia-smi/README.md
new file mode 100644
index 0000000..dd93d39
--- /dev/null
+++ b/.config/polybar/scripts/system-nvidia-smi/README.md
@@ -0,0 +1,26 @@
+# Script: system-nvidia-smi
+
+A script that shows the NVIDIA GPU utilization.
+
+
+## Dependencies
+
+* `nvidia-smi`
+
+
+## Configuration
+
+There are several `--query-gpu=` values. Use nvidia-smi `--help-query-gpu` for a complete list and description. The most notable are `fan.speed`, `memory.used`, `memory.total`, `driver_version`, `power.draw`, `pstate`.
+
+If you don't need custom labelling use instead:
+`nvidia-smi --query-gpu=utilization.gpu --format=csv,noheader`
+
+
+## Module
+
+```ini
+[module/system-nvidia-smi]
+type = custom/script
+exec = ~/polybar-scripts/system-nvidia-smi.sh
+interval = 10
+```
diff --git a/.config/polybar/scripts/system-nvidia-smi/system-nvidia-smi.sh b/.config/polybar/scripts/system-nvidia-smi/system-nvidia-smi.sh
new file mode 100644
index 0000000..52bad3f
--- /dev/null
+++ b/.config/polybar/scripts/system-nvidia-smi/system-nvidia-smi.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+nvidia-smi --query-gpu=utilization.gpu --format=csv,noheader,nounits | awk '{ print "GPU",""$1"","%"}'
diff --git a/.config/polybar/scripts/system-thinklight/README.md b/.config/polybar/scripts/system-thinklight/README.md
new file mode 100644
index 0000000..36e436b
--- /dev/null
+++ b/.config/polybar/scripts/system-thinklight/README.md
@@ -0,0 +1,15 @@
+# Script: system-thinklight
+
+A small script that displays the Thinklight state from ThinkPad ACPI driver.
+
+
+
+
+## Module
+
+```ini
+[module/system-thinklight]
+type = custom/script
+exec = ~/polybar-scripts/system-thinklight.sh
+interval = 10
+```
diff --git a/.config/polybar/scripts/system-thinklight/info-thinklight.sh b/.config/polybar/scripts/system-thinklight/info-thinklight.sh
new file mode 100644
index 0000000..258b57a
--- /dev/null
+++ b/.config/polybar/scripts/system-thinklight/info-thinklight.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+if [ "$(cat /sys/devices/platform/thinkpad_acpi/leds/tpacpi::thinklight/brightness)" = "0" ]; then
+ echo "#1"
+else
+ echo "#2 Thinklight"
+fi
diff --git a/.config/polybar/scripts/system-thinklight/screenshots/1.png b/.config/polybar/scripts/system-thinklight/screenshots/1.png
new file mode 100644
index 0000000..0dbb64d
Binary files /dev/null and b/.config/polybar/scripts/system-thinklight/screenshots/1.png differ
diff --git a/.config/polybar/scripts/system-uptime-pretty/README.md b/.config/polybar/scripts/system-uptime-pretty/README.md
new file mode 100644
index 0000000..b9255c2
--- /dev/null
+++ b/.config/polybar/scripts/system-uptime-pretty/README.md
@@ -0,0 +1,15 @@
+# Script: system-uptime-pretty
+
+A shell script which displays the output of `uptime --pretty` in a minimal fashion:
+
+`2d 1h 35m`
+
+
+## Module
+
+```ini
+[module/system-uptime-pretty]
+type = custom/script
+exec = ~/polybar-scripts/system-uptime-pretty.sh
+interval = 30
+```
diff --git a/.config/polybar/scripts/system-uptime-pretty/system-uptime-pretty.sh b/.config/polybar/scripts/system-uptime-pretty/system-uptime-pretty.sh
new file mode 100644
index 0000000..06cb8ca
--- /dev/null
+++ b/.config/polybar/scripts/system-uptime-pretty/system-uptime-pretty.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+uptime --pretty | sed 's/up //' | sed 's/\ years\?,/y/' | sed 's/\ weeks\?,/w/' | sed 's/\ days\?,/d/' | sed 's/\ hours\?,\?/h/' | sed 's/\ minutes\?/m/'
diff --git a/.config/polybar/scripts/system-usb-mount/README.md b/.config/polybar/scripts/system-usb-mount/README.md
new file mode 100644
index 0000000..885bfe9
--- /dev/null
+++ b/.config/polybar/scripts/system-usb-mount/README.md
@@ -0,0 +1,25 @@
+# Script: system-usb-mount
+
+A small script that shows your mounted and not mounted removable devices.
+
+Click left to mount all removable devices. Click right to unmount the devices. The removable devices are then turned off with `udisksctl power-off`.
+
+The mount option has a feature: You can also start a file manager and open the device when you mount it. Look at the example in the code: `terminal -e "bash -lc 'filemanager $mountpoint'" &`
+
+
+## Dependencies
+
+* `jq`
+* `udisks2`
+
+
+## Module
+
+```ini
+[module/system-usb-mount]
+type = custom/script
+exec = ~/polybar-scripts/system-usb-mount.sh
+interval = 5
+click-left = ~/polybar-scripts/system-usb-mount.sh --mount &
+click-right = ~/polybar-scripts/system-usb-mount.sh --unmount &
+```
diff --git a/.config/polybar/scripts/system-usb-mount/system-usb-mount.sh b/.config/polybar/scripts/system-usb-mount/system-usb-mount.sh
new file mode 100644
index 0000000..f632cf7
--- /dev/null
+++ b/.config/polybar/scripts/system-usb-mount/system-usb-mount.sh
@@ -0,0 +1,53 @@
+#!/bin/sh
+
+devices=$(lsblk -Jplno NAME,TYPE,RM,SIZE,MOUNTPOINT,VENDOR)
+
+case "$1" in
+ --mount)
+ for mount in $(echo "$devices" | jq -r '.blockdevices[] | select(.type == "part") | select(.rm == "1") | select(.mountpoint == null) | .name'); do
+ udisksctl mount --no-user-interaction -b "$mount"
+
+ # mountpoint=$(udisksctl mount --no-user-interaction -b $mount)
+ # mountpoint=$(echo $mountpoint | cut -d " " -f 4- | tr -d ".")
+ # terminal -e "bash -lc 'filemanager $mountpoint'" &
+ done
+ ;;
+ --unmount)
+ for unmount in $(echo "$devices" | jq -r '.blockdevices[] | select(.type == "part") | select(.rm == "1") | select(.mountpoint != null) | .name'); do
+ udisksctl unmount --no-user-interaction -b "$unmount"
+ udisksctl power-off --no-user-interaction -b "$unmount"
+ done
+ ;;
+ *)
+ output=""
+ counter=0
+
+ for unmounted in $(echo "$devices" | jq -r '.blockdevices[] | select(.type == "part") | select(.rm == "1") | select(.mountpoint == null) | .name'); do
+ unmounted=$(echo "$unmounted" | tr -d "[:digit:]")
+ unmounted=$(echo "$devices" | jq -r '.blockdevices[] | select(.name == "'"$unmounted"'") | .vendor')
+ unmounted=$(echo "$unmounted" | tr -d ' ')
+
+ if [ $counter -eq 0 ]; then
+ space=""
+ else
+ space=" "
+ fi
+ counter=$((counter + 1))
+
+ output="$output$space#1 $unmounted"
+ done
+
+ for mounted in $(echo "$devices" | jq -r '.blockdevices[] | select(.type == "part") | select(.rm == "1") | select(.mountpoint != null) | .size'); do
+ if [ $counter -eq 0 ]; then
+ space=""
+ else
+ space=" "
+ fi
+ counter=$((counter + 1))
+
+ output="$output$space#2 $mounted"
+ done
+
+ echo "$output"
+ ;;
+esac
diff --git a/.config/polybar/scripts/system-usb-udev/95-usb.rules b/.config/polybar/scripts/system-usb-udev/95-usb.rules
new file mode 100644
index 0000000..1cefd1d
--- /dev/null
+++ b/.config/polybar/scripts/system-usb-udev/95-usb.rules
@@ -0,0 +1,4 @@
+KERNEL=="sd*", ACTION=="add", ATTR{removable}=="1", \
+ RUN+="/home/user/.config/polybar/system-usb-udev.sh --update"
+KERNEL=="sd*", ACTION=="remove", \
+ RUN+="/home/user/.config/polybar/system-usb-udev.sh --update"
diff --git a/.config/polybar/scripts/system-usb-udev/README.md b/.config/polybar/scripts/system-usb-udev/README.md
new file mode 100644
index 0000000..b63bcf3
--- /dev/null
+++ b/.config/polybar/scripts/system-usb-udev/README.md
@@ -0,0 +1,35 @@
+# Script: system-usb-udev
+
+A small script that shows your mounted and not mounted removable devices. This is an extended version of [system-usb-mount](../system-usb-mount).
+
+Click left to mount all removable devices. Click right to unmount the devices. The removable devices are then turned off with `udisksctl power-off`.
+
+The mount option has a feature: You can also start a file manager and open the device when you mount it. Look at the example in the code: `terminal -e "bash -lc 'filemanager $mountpoint'" &`
+
+This script is able to display device changes in real time. For this udev is being used.
+
+
+
+
+
+## Dependencies
+
+* `jq`
+* `udisks2`
+
+
+## Configuration
+
+Copy `95-usb.rules` to `/etc/udev/rules.d/95-usb.rules`. Make sure that the paths in the file have been modified properly.
+
+
+## Module
+
+```ini
+[module/system-usb-udev]
+type = custom/script
+exec = ~/polybar-scripts/system-usb-udev.sh
+tail = true
+click-left = ~/polybar-scripts/system-usb-udev.sh --mount &
+click-right = ~/polybar-scripts/system-usb-udev.sh --unmount &
+```
diff --git a/.config/polybar/scripts/system-usb-udev/screenshots/1.png b/.config/polybar/scripts/system-usb-udev/screenshots/1.png
new file mode 100644
index 0000000..d89dc77
Binary files /dev/null and b/.config/polybar/scripts/system-usb-udev/screenshots/1.png differ
diff --git a/.config/polybar/scripts/system-usb-udev/screenshots/2.png b/.config/polybar/scripts/system-usb-udev/screenshots/2.png
new file mode 100644
index 0000000..9fef61c
Binary files /dev/null and b/.config/polybar/scripts/system-usb-udev/screenshots/2.png differ
diff --git a/.config/polybar/scripts/system-usb-udev/system-usb-udev.sh b/.config/polybar/scripts/system-usb-udev/system-usb-udev.sh
new file mode 100644
index 0000000..ea62b68
--- /dev/null
+++ b/.config/polybar/scripts/system-usb-udev/system-usb-udev.sh
@@ -0,0 +1,87 @@
+#!/bin/sh
+
+usb_print() {
+ devices=$(lsblk -Jplno NAME,TYPE,RM,SIZE,MOUNTPOINT,VENDOR)
+ output=""
+ counter=0
+
+ for unmounted in $(echo "$devices" | jq -r '.blockdevices[] | select(.type == "part") | select(.rm == true) | select(.mountpoint == null) | .name'); do
+ unmounted=$(echo "$unmounted" | tr -d "[:digit:]")
+ unmounted=$(echo "$devices" | jq -r '.blockdevices[] | select(.name == "'"$unmounted"'") | .vendor')
+ unmounted=$(echo "$unmounted" | tr -d ' ')
+
+ if [ $counter -eq 0 ]; then
+ space=""
+ else
+ space=" "
+ fi
+ counter=$((counter + 1))
+
+ output="$output$space#1 $unmounted"
+ done
+
+ for mounted in $(echo "$devices" | jq -r '.blockdevices[] | select(.type == "part") | select(.rm == true) | select(.mountpoint != null) | .size'); do
+ if [ $counter -eq 0 ]; then
+ space=""
+ else
+ space=" "
+ fi
+ counter=$((counter + 1))
+
+ output="$output$space#2 $mounted"
+ done
+
+ echo "$output"
+}
+
+usb_update() {
+ pid=$(cat "$path_pid")
+
+ if [ "$pid" != "" ]; then
+ kill -10 "$pid"
+ fi
+}
+
+path_pid="/tmp/polybar-system-usb-udev.pid"
+
+case "$1" in
+ --update)
+ usb_update
+ ;;
+ --mount)
+ devices=$(lsblk -Jplno NAME,TYPE,RM,MOUNTPOINT)
+
+ for mount in $(echo "$devices" | jq -r '.blockdevices[] | select(.type == "part") | select(.rm == true) | select(.mountpoint == null) | .name'); do
+ udisksctl mount --no-user-interaction -b "$mount"
+
+ # mountpoint=$(udisksctl mount --no-user-interaction -b $mount)
+ # mountpoint=$(echo $mountpoint | cut -d " " -f 4- | tr -d ".")
+ # terminal -e "bash -lc 'filemanager $mountpoint'"
+ done
+
+ usb_update
+ ;;
+ --unmount)
+ devices=$(lsblk -Jplno NAME,TYPE,RM,MOUNTPOINT)
+
+ for unmount in $(echo "$devices" | jq -r '.blockdevices[] | select(.type == "part") | select(.rm == true) | select(.mountpoint != null) | .name'); do
+ udisksctl unmount --no-user-interaction -b "$unmount"
+ udisksctl power-off --no-user-interaction -b "$unmount"
+ done
+
+ usb_update
+ ;;
+ *)
+ echo $$ > $path_pid
+
+ trap exit INT
+ trap "echo" USR1
+
+ while true; do
+ usb_print
+
+ sleep 60 &
+ wait
+ done
+ ;;
+esac
diff --git a/.config/polybar/scripts/ticker-crypto/README.md b/.config/polybar/scripts/ticker-crypto/README.md
new file mode 100644
index 0000000..c9094d5
--- /dev/null
+++ b/.config/polybar/scripts/ticker-crypto/README.md
@@ -0,0 +1,21 @@
+# Script: ticker-crypto
+
+A script that displays current Cryptocurrency quotes like Bitcoin.
+
+
+
+
+## Dependencies
+
+* `curl`
+* `jq`
+
+
+## Module
+
+```ini
+[module/ticker-crypto]
+type = custom/script
+exec = ~/polybar-scripts/ticker-crypto.sh
+interval = 600
+```
diff --git a/.config/polybar/scripts/ticker-crypto/screenshots/1.png b/.config/polybar/scripts/ticker-crypto/screenshots/1.png
new file mode 100644
index 0000000..e1d1a0b
Binary files /dev/null and b/.config/polybar/scripts/ticker-crypto/screenshots/1.png differ
diff --git a/.config/polybar/scripts/ticker-crypto/ticker-crypto.sh b/.config/polybar/scripts/ticker-crypto/ticker-crypto.sh
new file mode 100644
index 0000000..10c9079
--- /dev/null
+++ b/.config/polybar/scripts/ticker-crypto/ticker-crypto.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+API="https://api.kraken.com/0/public/Ticker"
+
+quote=$(curl -sf $API?pair=BTCEUR | jq -r ".result.XXBTZEUR.c[0]")
+quote=$(LANG=C printf "%.2f" "$quote")
+
+echo "#1 $quote €"
diff --git a/.config/polybar/scripts/ticker-forex/README.md b/.config/polybar/scripts/ticker-forex/README.md
new file mode 100644
index 0000000..485dc16
--- /dev/null
+++ b/.config/polybar/scripts/ticker-forex/README.md
@@ -0,0 +1,19 @@
+# Script: ticker-forex
+
+A small script that displays current exchange rates.
+
+
+## Dependencies
+
+* `curl`
+* `jq`
+
+
+## Module
+
+```ini
+[module/ticker-forex]
+type = custom/script
+exec = ~/polybar-scripts/ticker-forex.sh
+interval = 600
+```
diff --git a/.config/polybar/scripts/ticker-forex/ticker-forex.sh b/.config/polybar/scripts/ticker-forex/ticker-forex.sh
new file mode 100644
index 0000000..00edd4f
--- /dev/null
+++ b/.config/polybar/scripts/ticker-forex/ticker-forex.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+API="https://api.exchangeratesapi.io/latest"
+
+CURRENCY_BASE="EUR"
+CURRENCY_QUOTE="PLN"
+
+quote=$(curl -sf "$API?base=$CURRENCY_BASE&symbols=$CURRENCY_QUOTE" | jq -r ".rates.$CURRENCY_QUOTE")
+quote=$(LANG=C printf "%.2f" "$quote")
+
+
+echo "# $quote"
diff --git a/.config/polybar/scripts/updates-apt/README.md b/.config/polybar/scripts/updates-apt/README.md
new file mode 100644
index 0000000..8182a94
--- /dev/null
+++ b/.config/polybar/scripts/updates-apt/README.md
@@ -0,0 +1,13 @@
+# Script: updates-apt
+
+A script that shows if there are updates available through the apt package manager on Ubuntu and Debian-based systems.
+
+
+## Module
+
+```ini
+[module/updates-apt]
+type = custom/script
+exec = ~/polybar-scripts/updates-apt.sh
+interval = 600
+```
diff --git a/.config/polybar/scripts/updates-apt/updates-apt.sh b/.config/polybar/scripts/updates-apt/updates-apt.sh
new file mode 100644
index 0000000..07afafd
--- /dev/null
+++ b/.config/polybar/scripts/updates-apt/updates-apt.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+updates=$(apt list --upgradable 2> /dev/null | grep -c upgradable);
+
+if [ "$updates" -gt 0 ]; then
+ echo "# $updates"
+else
+ echo ""
+fi
diff --git a/.config/polybar/scripts/updates-aurhelper/README.md b/.config/polybar/scripts/updates-aurhelper/README.md
new file mode 100644
index 0000000..5dcc2ec
--- /dev/null
+++ b/.config/polybar/scripts/updates-aurhelper/README.md
@@ -0,0 +1,20 @@
+# Script: updates-aurhelper
+
+A script that shows if there are AUR updates for Arch Linux.
+
+
+## Dependencies
+
+The possibilities depend on your AUR helper. Not all helpers can report the pending updates.
+
+At the moment `yay`, `paru`, `trizen`, `pikaur`, `rua` and `cower` are documented. Take a look at the script to see how it works.
+
+
+## Module
+
+```ini
+[module/updates-aurhelper]
+type = custom/script
+exec = ~/polybar-scripts/updates-aurhelper.sh
+interval = 600
+```
diff --git a/.config/polybar/scripts/updates-aurhelper/updates-aurhelper.sh b/.config/polybar/scripts/updates-aurhelper/updates-aurhelper.sh
new file mode 100644
index 0000000..5dfa63b
--- /dev/null
+++ b/.config/polybar/scripts/updates-aurhelper/updates-aurhelper.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+if ! updates=$(yay -Qum 2> /dev/null | wc -l); then
+# if ! updates=$(paru -Qum 2> /dev/null | wc -l); then
+# if ! updates=$(cower -u 2> /dev/null | wc -l); then
+# if ! updates=$(trizen -Su --aur --quiet | wc -l); then
+# if ! updates=$(pikaur -Qua 2> /dev/null | wc -l); then
+# if ! updates=$(rua upgrade --printonly 2> /dev/null | wc -l); then
+ updates=0
+fi
+
+if [ "$updates" -gt 0 ]; then
+ echo "# $updates"
+else
+ echo ""
+fi
diff --git a/.config/polybar/scripts/updates-dnf/README.md b/.config/polybar/scripts/updates-dnf/README.md
new file mode 100644
index 0000000..45dc143
--- /dev/null
+++ b/.config/polybar/scripts/updates-dnf/README.md
@@ -0,0 +1,23 @@
+# Script: updates-dnf
+
+A script that shows if there are updates for dnf-based distributions like Fedora.
+
+
+
+
+## Configuration
+
+You have to add the `dnf` command to the `/etc/sudoers` NOPASSWD of your user:
+
+```
+user ALL=(ALL) NOPASSWD: /usr/bin/dnf updateinfo -q --list
+```
+
+## Module
+
+```ini
+[module/updates-dnf]
+type = custom/script
+exec = ~/polybar-scripts/updates-dnf.sh
+interval = 600
+```
diff --git a/.config/polybar/scripts/updates-dnf/screenshots/1.png b/.config/polybar/scripts/updates-dnf/screenshots/1.png
new file mode 100644
index 0000000..d51f301
Binary files /dev/null and b/.config/polybar/scripts/updates-dnf/screenshots/1.png differ
diff --git a/.config/polybar/scripts/updates-dnf/updates-dnf.sh b/.config/polybar/scripts/updates-dnf/updates-dnf.sh
new file mode 100644
index 0000000..115a5e4
--- /dev/null
+++ b/.config/polybar/scripts/updates-dnf/updates-dnf.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+updates=$(dnf updateinfo -q --list | wc -l)
+
+if [ "$updates" -gt 0 ]; then
+ echo "# $updates"
+else
+ echo ""
+fi
diff --git a/.config/polybar/scripts/updates-flatpak/README.md b/.config/polybar/scripts/updates-flatpak/README.md
new file mode 100644
index 0000000..cdfdb9b
--- /dev/null
+++ b/.config/polybar/scripts/updates-flatpak/README.md
@@ -0,0 +1,13 @@
+# Script: updates-flatpak
+
+A script that shows if there are updates for FlatPak.
+
+
+## Module
+
+```ini
+[module/updates-flatpak]
+type = custom/script
+exec = ~/polybar-scripts/updates-flatpak.sh
+interval = 600
+```
diff --git a/.config/polybar/scripts/updates-flatpak/updates-flatpak.sh b/.config/polybar/scripts/updates-flatpak/updates-flatpak.sh
new file mode 100644
index 0000000..b3cd7d2
--- /dev/null
+++ b/.config/polybar/scripts/updates-flatpak/updates-flatpak.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+updates=$(flatpak update 2>/dev/null | tail -n +5 | grep -Ecv "^$|^Proceed|^Nothing")
+
+if [ "$updates" -gt 0 ]; then
+ echo "flatpak: $updates"
+else
+ echo ""
+fi
diff --git a/.config/polybar/scripts/updates-fwupd/README.md b/.config/polybar/scripts/updates-fwupd/README.md
new file mode 100644
index 0000000..3b6a0f1
--- /dev/null
+++ b/.config/polybar/scripts/updates-fwupd/README.md
@@ -0,0 +1,18 @@
+# Script: updates-fwupd
+
+A script that shows if there are firmware updates available.
+
+
+## Dependencies
+
+* `fwupd`
+
+
+## Module
+
+```ini
+[module/updates-fwupd]
+type = custom/script
+exec = ~/polybar-scripts/updates-fwupd.sh
+interval = 3600
+```
diff --git a/.config/polybar/scripts/updates-fwupd/updates-fwupdmgr.sh b/.config/polybar/scripts/updates-fwupd/updates-fwupdmgr.sh
new file mode 100644
index 0000000..0b6198f
--- /dev/null
+++ b/.config/polybar/scripts/updates-fwupd/updates-fwupdmgr.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+fwupdmgr refresh >> /dev/null 2>&1
+
+updates=$(fwupdmgr get-updates 2> /dev/null | grep -c "Updatable")
+
+if [ "$updates" -gt 0 ]; then
+ echo "# $updates"
+else
+ echo ""
+fi
diff --git a/.config/polybar/scripts/updates-pacman-aurhelper/README.md b/.config/polybar/scripts/updates-pacman-aurhelper/README.md
new file mode 100644
index 0000000..8fe290c
--- /dev/null
+++ b/.config/polybar/scripts/updates-pacman-aurhelper/README.md
@@ -0,0 +1,26 @@
+# Script: updates-pacman-aurhelper
+
+A script that shows if there are updates for Arch Linux and AUR updates.
+
+See also [updates-pacman](../updates-pacman) and [updates-aurhelper](../updates-aurhelper).
+
+
+
+
+## Dependencies
+
+* `pacman-contrib`
+
+The possibilities depend on your AUR helper. Not all helpers can report the pending updates.
+
+At the moment `yay`, `paru`, `trizen`, `pikaur`, `rua` and `cower` are documented. Take a look at the script to see how it works.
+
+
+## Module
+
+```ini
+[module/updates-pacman-aurhelper]
+type = custom/script
+exec = ~/polybar-scripts/updates-pacman-aurhelper.sh
+interval = 600
+```
diff --git a/.config/polybar/scripts/updates-pacman-aurhelper/screenshots/1.png b/.config/polybar/scripts/updates-pacman-aurhelper/screenshots/1.png
new file mode 100644
index 0000000..b69bbc3
Binary files /dev/null and b/.config/polybar/scripts/updates-pacman-aurhelper/screenshots/1.png differ
diff --git a/.config/polybar/scripts/updates-pacman-aurhelper/updates-pacman-aurhelper.sh b/.config/polybar/scripts/updates-pacman-aurhelper/updates-pacman-aurhelper.sh
new file mode 100644
index 0000000..5971118
--- /dev/null
+++ b/.config/polybar/scripts/updates-pacman-aurhelper/updates-pacman-aurhelper.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+if ! updates_arch=$(checkupdates 2> /dev/null | wc -l ); then
+ updates_arch=0
+fi
+
+if ! updates_aur=$(yay -Qum 2> /dev/null | wc -l); then
+# if ! updates_aur=$(paru -Qum 2> /dev/null | wc -l); then
+# if ! updates_aur=$(cower -u 2> /dev/null | wc -l); then
+# if ! updates_aur=$(trizen -Su --aur --quiet | wc -l); then
+# if ! updates_aur=$(pikaur -Qua 2> /dev/null | wc -l); then
+# if ! updates_aur=$(rua upgrade --printonly 2> /dev/null | wc -l); then
+ updates_aur=0
+fi
+
+updates=$((updates_arch + updates_aur))
+
+if [ "$updates" -gt 0 ]; then
+ echo "# $updates"
+else
+ echo ""
+fi
diff --git a/.config/polybar/scripts/updates-pacman/README.md b/.config/polybar/scripts/updates-pacman/README.md
new file mode 100644
index 0000000..38131c2
--- /dev/null
+++ b/.config/polybar/scripts/updates-pacman/README.md
@@ -0,0 +1,18 @@
+# Script: updates-pacman
+
+A script that shows if there are updates for pacman-based distributions like Arch Linux or Manjaro.
+
+
+## Dependencies
+
+* `pacman-contrib`
+
+
+## Module
+
+```ini
+[module/updates-pacman]
+type = custom/script
+exec = ~/polybar-scripts/updates-pacman.sh
+interval = 600
+```
diff --git a/.config/polybar/scripts/updates-pacman/updates-pacman.sh b/.config/polybar/scripts/updates-pacman/updates-pacman.sh
new file mode 100644
index 0000000..3c0a27d
--- /dev/null
+++ b/.config/polybar/scripts/updates-pacman/updates-pacman.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+if ! updates=$(checkupdates 2> /dev/null | wc -l ); then
+ updates=0
+fi
+
+if [ "$updates" -gt 0 ]; then
+ echo "# $updates"
+else
+ echo ""
+fi
diff --git a/.config/polybar/scripts/updates-xbps/README.md b/.config/polybar/scripts/updates-xbps/README.md
new file mode 100644
index 0000000..e287c5c
--- /dev/null
+++ b/.config/polybar/scripts/updates-xbps/README.md
@@ -0,0 +1,13 @@
+# Script: updates-xbps
+
+A script that shows if there are updates for xbps-based distributions like Void Linux.
+
+
+## Module
+
+```ini
+[module/updates-xbps]
+type = custom/script
+exec = ~/polybar-scripts/updates-xbps.sh
+interval = 20
+```
diff --git a/.config/polybar/scripts/updates-xbps/updates-xbps.sh b/.config/polybar/scripts/updates-xbps/updates-xbps.sh
new file mode 100644
index 0000000..f575203
--- /dev/null
+++ b/.config/polybar/scripts/updates-xbps/updates-xbps.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+updates=$(xbps-install -Mun 2> /dev/null | wc -l)
+
+if [ -n "$updates" ] && [ "$updates" -gt 0 ]; then
+ echo "# $updates"
+else
+ echo ""
+fi
diff --git a/.config/polybar/scripts/vpn-anyconnect-status/README.md b/.config/polybar/scripts/vpn-anyconnect-status/README.md
new file mode 100644
index 0000000..0b9a1d0
--- /dev/null
+++ b/.config/polybar/scripts/vpn-anyconnect-status/README.md
@@ -0,0 +1,28 @@
+# Script: vpn-anyconnect-status
+
+A small script to show the anyconnect status.
+
+If an interface named `cscotun` exists the IP address will be displayed. Otherwise it displays `VPN DISCONNECTED`.
+
+
+
+
+
+## Dependencies
+
+* `ifconfig`
+
+
+## Configuration
+
+The Icon is `賓` from [FantasqueSansMono](https://github.com/ryanoasis/nerd-fonts/tree/master/patched-fonts/FantasqueSansMono/Regular/complete).
+
+
+## Module
+
+```ini
+[module/vpn-anyconnect-status]
+type = custom/script
+exec = ~/bin/vpnstatus.sh
+interval = 5
+```
diff --git a/.config/polybar/scripts/vpn-anyconnect-status/screenshots/1.png b/.config/polybar/scripts/vpn-anyconnect-status/screenshots/1.png
new file mode 100644
index 0000000..84467ee
Binary files /dev/null and b/.config/polybar/scripts/vpn-anyconnect-status/screenshots/1.png differ
diff --git a/.config/polybar/scripts/vpn-anyconnect-status/screenshots/2.png b/.config/polybar/scripts/vpn-anyconnect-status/screenshots/2.png
new file mode 100644
index 0000000..069417e
Binary files /dev/null and b/.config/polybar/scripts/vpn-anyconnect-status/screenshots/2.png differ
diff --git a/.config/polybar/scripts/vpn-anyconnect-status/vpn-anyconnect-status.sh b/.config/polybar/scripts/vpn-anyconnect-status/vpn-anyconnect-status.sh
new file mode 100644
index 0000000..77ea379
--- /dev/null
+++ b/.config/polybar/scripts/vpn-anyconnect-status/vpn-anyconnect-status.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+IFACE=$(ifconfig | grep cscotun | awk '{print $1}')
+
+if [ "$IFACE" = "cscotun*" ]; then
+ echo "#1 %{u#55aa55}$(ifconfig cscotun0 | grep inet | awk '{print $2}' | cut -f2 -d ':')%{u-}"
+else
+ echo "#1 %{F#FF0000}%{u#FF0000}VPN DISCONNECTED%{u-}%{F-}"
+fi
diff --git a/.config/polybar/scripts/vpn-expressvpn-status/README.md b/.config/polybar/scripts/vpn-expressvpn-status/README.md
new file mode 100644
index 0000000..45185eb
--- /dev/null
+++ b/.config/polybar/scripts/vpn-expressvpn-status/README.md
@@ -0,0 +1,24 @@
+# Script: vpn-expressvpn-status
+
+A small script that shows the status of ExpressVPN.
+
+It includes a `--toggle` option to connect/disconnect.
+
+
+
+
+
+## Dependencies
+
+* [`ExpressVPN client`](https://www.expressvpn.com/vpn-software/vpn-linux)
+
+
+## Module
+
+```ini
+[module/vpn-expressvpn-status]
+type = custom/script
+exec = ~/polybar-scripts/vpn-expressvpn-status.sh
+click-left = ~/polybar-scripts/vpn-expressvpn-status.sh --toggle &
+interval = 10
+```
diff --git a/.config/polybar/scripts/vpn-expressvpn-status/screenshots/1.png b/.config/polybar/scripts/vpn-expressvpn-status/screenshots/1.png
new file mode 100644
index 0000000..088548f
Binary files /dev/null and b/.config/polybar/scripts/vpn-expressvpn-status/screenshots/1.png differ
diff --git a/.config/polybar/scripts/vpn-expressvpn-status/screenshots/2.png b/.config/polybar/scripts/vpn-expressvpn-status/screenshots/2.png
new file mode 100644
index 0000000..2bf28fd
Binary files /dev/null and b/.config/polybar/scripts/vpn-expressvpn-status/screenshots/2.png differ
diff --git a/.config/polybar/scripts/vpn-expressvpn-status/vpn-expressvpn-status.sh b/.config/polybar/scripts/vpn-expressvpn-status/vpn-expressvpn-status.sh
new file mode 100644
index 0000000..5441a4e
--- /dev/null
+++ b/.config/polybar/scripts/vpn-expressvpn-status/vpn-expressvpn-status.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+STATUS=$(expressvpn status)
+
+expressvpn_toggle() {
+ if [ "$STATUS" != 'Not connected' ]; then
+ expressvpn disconnect
+ else
+ expressvpn connect
+ fi
+}
+
+expressvpn_status() {
+ if [ "$STATUS" != 'Not connected' ]; then
+ echo "$STATUS" | head -n1 | cut -d'-' -f2
+ else
+ echo 'not connected'
+ fi
+}
+
+case "$1" in
+ --toggle)
+ expressvpn_toggle
+ ;;
+ *)
+ expressvpn_status
+ ;;
+esac
diff --git a/.config/polybar/scripts/vpn-networkmanager-status/README.md b/.config/polybar/scripts/vpn-networkmanager-status/README.md
new file mode 100644
index 0000000..1080248
--- /dev/null
+++ b/.config/polybar/scripts/vpn-networkmanager-status/README.md
@@ -0,0 +1,15 @@
+# Script: vpn-networkmanager-status
+
+A simple script that shows the name of the VPN started via NetworkManager.
+
+
+
+
+## Module
+
+```ini
+[module/vpn-networkmanager-status]
+type = custom/script
+exec = ~/polybar-scripts/vpn-networkmanager-status.sh
+interval = 10
+```
diff --git a/.config/polybar/scripts/vpn-networkmanager-status/screenshots/1.png b/.config/polybar/scripts/vpn-networkmanager-status/screenshots/1.png
new file mode 100644
index 0000000..07b72cf
Binary files /dev/null and b/.config/polybar/scripts/vpn-networkmanager-status/screenshots/1.png differ
diff --git a/.config/polybar/scripts/vpn-networkmanager-status/vpn-networkmanager-status.sh b/.config/polybar/scripts/vpn-networkmanager-status/vpn-networkmanager-status.sh
new file mode 100644
index 0000000..e393c5a
--- /dev/null
+++ b/.config/polybar/scripts/vpn-networkmanager-status/vpn-networkmanager-status.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+vpn="$(nmcli -t -f name,type connection show --order name --active 2>/dev/null | grep vpn | head -1 | cut -d ':' -f 1)"
+
+if [ -n "$vpn" ]; then
+ echo "#2 VPN: $vpn"
+else
+ echo "#2 VPN: DOWN "
+fi
diff --git a/.config/polybar/scripts/vpn-nordvpn-status/README.md b/.config/polybar/scripts/vpn-nordvpn-status/README.md
new file mode 100644
index 0000000..0617ef0
--- /dev/null
+++ b/.config/polybar/scripts/vpn-nordvpn-status/README.md
@@ -0,0 +1,16 @@
+# Script: vpn-nordvpn-status
+
+A small script that shows the status of NordVpn, with click-able actions that allow you to connect / reconnect. When connected it will display the City of the connection.
+
+
+
+
+
+## Module
+
+```ini
+[module/vpn-nordvpn-status]
+type = custom/script
+exec = ~/polybar-scripts/vpn-nordvpn-status.sh
+interval = 5
+```
diff --git a/.config/polybar/scripts/vpn-nordvpn-status/screenshots/1.png b/.config/polybar/scripts/vpn-nordvpn-status/screenshots/1.png
new file mode 100644
index 0000000..8dc28dd
Binary files /dev/null and b/.config/polybar/scripts/vpn-nordvpn-status/screenshots/1.png differ
diff --git a/.config/polybar/scripts/vpn-nordvpn-status/screenshots/2.png b/.config/polybar/scripts/vpn-nordvpn-status/screenshots/2.png
new file mode 100644
index 0000000..568b32b
Binary files /dev/null and b/.config/polybar/scripts/vpn-nordvpn-status/screenshots/2.png differ
diff --git a/.config/polybar/scripts/vpn-nordvpn-status/vpn-nordvpn-status.sh b/.config/polybar/scripts/vpn-nordvpn-status/vpn-nordvpn-status.sh
new file mode 100644
index 0000000..beaaa74
--- /dev/null
+++ b/.config/polybar/scripts/vpn-nordvpn-status/vpn-nordvpn-status.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+STATUS=$(nordvpn status | grep Status | tr -d ' ' | cut -d ':' -f2)
+
+if [ "$STATUS" = "Connected" ]; then
+ echo "%{F#82E0AA}%{A1:nordvpn d:}$(nordvpn status | grep City | cut -d ':' -f2)%{A}%{F-}"
+else
+ echo "%{F#f00}%{A1:nordvpn c:}no vpn%{A}%{F-}"
+fi
diff --git a/.config/polybar/scripts/vpn-openvpn-isrunning/README.md b/.config/polybar/scripts/vpn-openvpn-isrunning/README.md
new file mode 100644
index 0000000..b38e270
--- /dev/null
+++ b/.config/polybar/scripts/vpn-openvpn-isrunning/README.md
@@ -0,0 +1,15 @@
+# Script: vpn-openvpn-isrunning
+
+A simple script which shows if OpenVPN is running.
+
+
+
+
+## Module
+
+```ini
+[module/vpn-openvpn-isrunning]
+type = custom/script
+exec = ~/polybar-scripts/vpn-openvpn-isrunning.sh
+interval = 5
+```
diff --git a/.config/polybar/scripts/vpn-openvpn-isrunning/screenshots/1.png b/.config/polybar/scripts/vpn-openvpn-isrunning/screenshots/1.png
new file mode 100644
index 0000000..f64472f
Binary files /dev/null and b/.config/polybar/scripts/vpn-openvpn-isrunning/screenshots/1.png differ
diff --git a/.config/polybar/scripts/vpn-openvpn-isrunning/vpn-openvpn-isrunning.sh b/.config/polybar/scripts/vpn-openvpn-isrunning/vpn-openvpn-isrunning.sh
new file mode 100644
index 0000000..9de9d65
--- /dev/null
+++ b/.config/polybar/scripts/vpn-openvpn-isrunning/vpn-openvpn-isrunning.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+connection=$(pgrep -a openvpn$ | head -n 1 | awk '{print $NF }' | cut -d '.' -f 1)
+
+if [ -n "$connection" ]; then
+ echo "VPN: connection"
+else
+ echo ""
+fi
diff --git a/.config/polybar/scripts/vpn-openvpn-status/README.md b/.config/polybar/scripts/vpn-openvpn-status/README.md
new file mode 100644
index 0000000..eeaf5cb
--- /dev/null
+++ b/.config/polybar/scripts/vpn-openvpn-status/README.md
@@ -0,0 +1,28 @@
+# Script: vpn-openvpn-status
+
+A script that shows if OpenVPN is running and which configuration file it uses.
+
+
+
+
+
+## Configuration
+
+* The configuration files must have an extension, e.g. `.ovpn`.
+* The configuration files must be stored in a directory, e.g. `/etc/openvpn/conf.d`.
+
+Launch OpenVPN with the following command:
+
+```
+openvpn --daemon --auth-nocache --cd "/etc/openvpn/conf.d" --config "UK-Southampton.ovpn"
+```
+
+
+## Module
+
+```ini
+[module/vpn-openvpn-status]
+type = custom/script
+exec = ~/polybar-scripts/vpn-openvpn-status.sh
+interval = 5
+```
diff --git a/.config/polybar/scripts/vpn-openvpn-status/screenshots/1.png b/.config/polybar/scripts/vpn-openvpn-status/screenshots/1.png
new file mode 100644
index 0000000..a854d70
Binary files /dev/null and b/.config/polybar/scripts/vpn-openvpn-status/screenshots/1.png differ
diff --git a/.config/polybar/scripts/vpn-openvpn-status/screenshots/2.png b/.config/polybar/scripts/vpn-openvpn-status/screenshots/2.png
new file mode 100644
index 0000000..cf88c19
Binary files /dev/null and b/.config/polybar/scripts/vpn-openvpn-status/screenshots/2.png differ
diff --git a/.config/polybar/scripts/vpn-openvpn-status/vpn-openvpn-status.sh b/.config/polybar/scripts/vpn-openvpn-status/vpn-openvpn-status.sh
new file mode 100644
index 0000000..01063a9
--- /dev/null
+++ b/.config/polybar/scripts/vpn-openvpn-status/vpn-openvpn-status.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+printf "VPN: " && (pgrep -a openvpn$ | head -n 1 | awk '{print $NF }' | cut -d '.' -f 1 && echo down) | head -n 1
diff --git a/.config/polybar/scripts/vpn-wireguard-wg/README.md b/.config/polybar/scripts/vpn-wireguard-wg/README.md
new file mode 100644
index 0000000..53c909e
--- /dev/null
+++ b/.config/polybar/scripts/vpn-wireguard-wg/README.md
@@ -0,0 +1,26 @@
+# Script: vpn-wireguard-wg
+
+A script that shows the status of a chosen Wireguard connection.
+
+
+
+
+
+## Configuration
+
+You have to add the `wg` and `wg-quick` command to the `/etc/sudoers` NOPASSWD of your user:
+
+```ini
+user ALL=(ALL) NOPASSWD: /usr/bin/wg
+user ALL=(ALL) NOPASSWD: /usr/bin/wg-quick
+```
+
+## Module
+
+```ini
+[module/vpn-wireguard-wg]
+type = custom/script
+exec = ~/polybar-scripts/vpn-wireguard-wg.sh
+interval = 5
+click-left = ~/polybar-scripts//vpn-wireguard-wg.sh --toggle &
+```
diff --git a/.config/polybar/scripts/vpn-wireguard-wg/screenshots/1.png b/.config/polybar/scripts/vpn-wireguard-wg/screenshots/1.png
new file mode 100644
index 0000000..eac3341
Binary files /dev/null and b/.config/polybar/scripts/vpn-wireguard-wg/screenshots/1.png differ
diff --git a/.config/polybar/scripts/vpn-wireguard-wg/screenshots/2.png b/.config/polybar/scripts/vpn-wireguard-wg/screenshots/2.png
new file mode 100644
index 0000000..3b8c761
Binary files /dev/null and b/.config/polybar/scripts/vpn-wireguard-wg/screenshots/2.png differ
diff --git a/.config/polybar/scripts/vpn-wireguard-wg/vpn-wireguard-wg.sh b/.config/polybar/scripts/vpn-wireguard-wg/vpn-wireguard-wg.sh
new file mode 100644
index 0000000..87b2779
--- /dev/null
+++ b/.config/polybar/scripts/vpn-wireguard-wg/vpn-wireguard-wg.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+connection_status() {
+ if [ -f "$config" ]; then
+ connection=$(sudo wg show "$config_name" 2>/dev/null | head -n 1 | awk '{print $NF }')
+
+ if [ "$connection" = "$config_name" ]; then
+ echo "1"
+ else
+ echo "2"
+ fi
+ else
+ echo "3"
+ fi
+}
+
+config="$HOME/wg/wireguard.conf"
+config_name=$(basename "${config%.*}")
+
+case "$1" in
+--toggle)
+ if [ "$(connection_status)" = "1" ]; then
+ sudo wg-quick down "$config" 2>/dev/null
+ else
+ sudo wg-quick up "$config" 2>/dev/null
+ fi
+ ;;
+*)
+ if [ "$(connection_status)" = "1" ]; then
+ echo "#1 $config_name"
+ elif [ "$(connection_status)" = "3" ]; then
+ echo "#3 Config not found!"
+ else
+ echo "#2 down"
+ fi
+ ;;
+esac
diff --git a/.config/redshift/redshift.conf b/.config/redshift/redshift.conf
new file mode 100644
index 0000000..263d53e
--- /dev/null
+++ b/.config/redshift/redshift.conf
@@ -0,0 +1,71 @@
+; Global settings for redshift
+[redshift]
+; Set the day and night screen temperatures
+temp-day=5700
+temp-night=3500
+
+; Disable the smooth fade between temperatures when Redshift starts and stops.
+; 0 will cause an immediate change between screen temperatures.
+; 1 will gradually apply the new screen temperature over a couple of seconds.
+fade=1
+
+; Solar elevation thresholds.
+; By default, Redshift will use the current elevation of the sun to determine
+; whether it is daytime, night or in transition (dawn/dusk). When the sun is
+; above the degrees specified with elevation-high it is considered daytime and
+; below elevation-low it is considered night.
+;elevation-high=3
+;elevation-low=-6
+
+; Custom dawn/dusk intervals.
+; Instead of using the solar elevation, the time intervals of dawn and dusk
+; can be specified manually. The times must be specified as HH:MM in 24-hour
+; format.
+;dawn-time=6:00-7:45
+;dusk-time=18:35-20:15
+
+; Set the screen brightness. Default is 1.0.
+;brightness=0.9
+; It is also possible to use different settings for day and night
+; since version 1.8.
+;brightness-day=0.7
+;brightness-night=0.4
+; Set the screen gamma (for all colors, or each color channel
+; individually)
+;gamma=0.8
+;gamma=0.8:0.7:0.8
+; This can also be set individually for day and night since
+; version 1.10.
+;gamma-day=0.8:0.7:0.8
+;gamma-night=0.6
+
+; Set the location-provider: 'geoclue2', 'manual'
+; type 'redshift -l list' to see possible values.
+; The location provider settings are in a different section.
+location-provider=manual
+
+; Set the adjustment-method: 'randr', 'vidmode'
+; type 'redshift -m list' to see all possible values.
+; 'randr' is the preferred method, 'vidmode' is an older API.
+; but works in some cases when 'randr' does not.
+; The adjustment method settings are in a different section.
+adjustment-method=randr
+
+; Configuration of the location-provider:
+; type 'redshift -l PROVIDER:help' to see the settings.
+; ex: 'redshift -l manual:help'
+; Keep in mind that longitudes west of Greenwich (e.g. the Americas)
+; are negative numbers.
+[manual]
+lat=45.8
+lon=-93.1
+
+; Configuration of the adjustment-method
+; type 'redshift -m METHOD:help' to see the settings.
+; ex: 'redshift -m randr:help'
+; In this example, randr is configured to adjust only screen 0.
+; Note that the numbering starts from 0, so this is actually the first screen.
+; If this option is not specified, Redshift will try to adjust _all_ screens.
+;[randr]
+;screen=0
+
diff --git a/.config/rofi/config.rasi b/.config/rofi/config.rasi
index 41880ff..45a9701 100644
--- a/.config/rofi/config.rasi
+++ b/.config/rofi/config.rasi
@@ -10,6 +10,14 @@ configuration {
drun-display-format: "{icon} {name}";
sidebar-mode: true;
terminal: "kitty";
+
+ kb-row-up: "Up,Control+k,Shift+Tab,Shift+ISO_Left_Tab";
+ kb-row-down: "Down,Control+j";
+ kb-accept-entry: "Control+m,Return,KP_Enter";
+ kb-remove-to-eol: "Control+Shift+e";
+ /*kb-mode-next: "Shift+Right,Control+Tab,Control+l";*/
+ kb-mode-previous: "Shift+Left,Control+Shift+Tab,Control+h";
+ kb-remove-char-back: "BackSpace";
}
@theme "/home/april/.config/rofi/themes/everforest.rasi"
diff --git a/.config/rofi/scripts/rofi-power-menu b/.config/rofi/scripts/rofi-power-menu
new file mode 100755
index 0000000..7f0aab0
--- /dev/null
+++ b/.config/rofi/scripts/rofi-power-menu
@@ -0,0 +1,280 @@
+#!/usr/bin/env bash
+
+# This script defines just a mode for rofi instead of being a self-contained
+# executable that launches rofi by itself. This makes it more flexible than
+# running rofi inside this script as now the user can call rofi as one pleases.
+# For instance:
+#
+# rofi -show powermenu -modi powermenu:./rofi-power-menu
+#
+# See README.md for more information.
+
+set -e
+set -u
+
+# All supported choices
+all=(shutdown reboot suspend hibernate logout lockscreen)
+
+# By default, show all (i.e., just copy the array)
+show=("${all[@]}")
+
+declare -A texts
+texts[lockscreen]="lock screen"
+texts[switchuser]="switch user"
+texts[logout]="log out"
+texts[suspend]="suspend"
+texts[hibernate]="hibernate"
+texts[reboot]="reboot"
+texts[shutdown]="shut down"
+
+declare -A icons
+icons[lockscreen]="\Uf033e"
+icons[switchuser]="\Uf0019"
+icons[logout]="\Uf0343"
+icons[suspend]="\Uf04b2"
+icons[hibernate]="\Uf02ca"
+icons[reboot]="\Uf0709"
+icons[shutdown]="\Uf0425"
+icons[cancel]="\Uf0156"
+
+declare -A actions
+actions[lockscreen]="loginctl lock-session ${XDG_SESSION_ID-}"
+#actions[switchuser]="???"
+actions[logout]="loginctl terminate-session ${XDG_SESSION_ID-}"
+actions[suspend]="systemctl suspend"
+actions[hibernate]="systemctl hibernate"
+actions[reboot]="systemctl reboot"
+actions[shutdown]="systemctl poweroff"
+
+# By default, ask for confirmation for actions that are irreversible
+confirmations=(reboot shutdown logout)
+
+# By default, no dry run
+dryrun=false
+showsymbols=true
+showtext=true
+
+function check_valid {
+ option="$1"
+ shift 1
+ for entry in "${@}"
+ do
+ if [ -z "${actions[$entry]+x}" ]
+ then
+ echo "Invalid choice in $1: $entry" >&2
+ exit 1
+ fi
+ done
+}
+
+# Parse command-line options
+parsed=$(getopt --options=h --longoptions=help,dry-run,confirm:,choices:,choose:,symbols,no-symbols,text,no-text,symbols-font: --name "$0" -- "$@")
+if [ $? -ne 0 ]; then
+ echo 'Terminating...' >&2
+ exit 1
+fi
+eval set -- "$parsed"
+unset parsed
+while true; do
+ case "$1" in
+ "-h"|"--help")
+ echo "rofi-power-menu - a power menu mode for Rofi"
+ echo
+ echo "Usage: rofi-power-menu [--choices CHOICES] [--confirm CHOICES]"
+ echo " [--choose CHOICE] [--dry-run] [--symbols|--no-symbols]"
+ echo
+ echo "Use with Rofi in script mode. For instance, to ask for shutdown or reboot:"
+ echo
+ echo " rofi -show menu -modi \"menu:rofi-power-menu --choices=shutdown/reboot\""
+ echo
+ echo "Available options:"
+ echo " --dry-run Don't perform the selected action but print it to stderr."
+ echo " --choices CHOICES Show only the selected choices in the given order. Use /"
+ echo " as the separator. Available choices are lockscreen,"
+ echo " logout,suspend, hibernate, reboot and shutdown. By"
+ echo " default, all available choices are shown."
+ echo " --confirm CHOICES Require confirmation for the gives choices only. Use / as"
+ echo " the separator. Available choices are lockscreen, logout,"
+ echo " suspend, hibernate, reboot and shutdown. By default, only"
+ echo " irreversible actions logout, reboot and shutdown require"
+ echo " confirmation."
+ echo " --choose CHOICE Preselect the given choice and only ask for a"
+ echo " confirmation (if confirmation is set to be requested). It"
+ echo " is strongly recommended to combine this option with"
+ echo " --confirm=CHOICE if the choice wouldn't require"
+ echo " confirmation by default. Available choices are"
+ echo " lockscreen, logout, suspend, hibernate, reboot and"
+ echo " shutdown."
+ echo " --[no-]symbols Show Unicode symbols or not. Requires a font with support"
+ echo " for the symbols. Use, for instance, fonts from the"
+ echo " Nerdfonts collection. By default, they are shown"
+ echo " --[no-]text Show text description or not."
+ echo " --symbols-font FONT Use the given font for symbols. By default, the symbols"
+ echo " use the same font as the text. That font is configured"
+ echo " with rofi."
+ echo " -h,--help Show this help text."
+ exit 0
+ ;;
+ "--dry-run")
+ dryrun=true
+ shift 1
+ ;;
+ "--confirm")
+ IFS='/' read -ra confirmations <<< "$2"
+ check_valid "$1" "${confirmations[@]}"
+ shift 2
+ ;;
+ "--choices")
+ IFS='/' read -ra show <<< "$2"
+ check_valid "$1" "${show[@]}"
+ shift 2
+ ;;
+ "--choose")
+ # Check that the choice is valid
+ check_valid "$1" "$2"
+ selectionID="$2"
+ shift 2
+ ;;
+ "--symbols")
+ showsymbols=true
+ shift 1
+ ;;
+ "--no-symbols")
+ showsymbols=false
+ shift 1
+ ;;
+ "--text")
+ showtext=true
+ shift 1
+ ;;
+ "--no-text")
+ showtext=false
+ shift 1
+ ;;
+ "--symbols-font")
+ symbols_font="$2"
+ shift 2
+ ;;
+ "--")
+ shift
+ break
+ ;;
+ *)
+ echo "Internal error" >&2
+ exit 1
+ ;;
+ esac
+done
+
+if [ "$showsymbols" = "false" -a "$showtext" = "false" ]
+then
+ echo "Invalid options: cannot have --no-symbols and --no-text enabled at the same time." >&2
+ exit 1
+fi
+
+# Define the messages after parsing the CLI options so that it is possible to
+# configure them in the future.
+
+function write_message {
+ if [ -z ${symbols_font+x} ];
+ then
+ icon="$1 "
+ else
+ icon="$1 "
+ fi
+ text="$2 "
+ if [ "$showsymbols" = "true" ]
+ then
+ if [ "$showtext" = "true" ]
+ then
+ echo -n "\u200e$icon \u2068$text\u2069"
+ else
+ echo -n "\u200e$icon"
+ fi
+ else
+ echo -n "$text"
+ fi
+}
+
+function print_selection {
+ echo -e "$1" | $(read -r -d '' entry; echo "echo $entry")
+}
+
+declare -A messages
+declare -A confirmationMessages
+for entry in "${all[@]}"
+do
+ messages[$entry]=$(write_message "${icons[$entry]}" "${texts[$entry]^}")
+done
+for entry in "${all[@]}"
+do
+ confirmationMessages[$entry]=$(write_message "${icons[$entry]}" "Yes, ${texts[$entry]}")
+done
+confirmationMessages[cancel]=$(write_message "${icons[cancel]}" "No, cancel")
+
+if [ $# -gt 0 ]
+then
+ # If arguments given, use those as the selection
+ selection="${@}"
+else
+ # Otherwise, use the CLI passed choice if given
+ if [ -n "${selectionID+x}" ]
+ then
+ selection="${messages[$selectionID]}"
+ fi
+fi
+
+# Don't allow custom entries
+echo -e "\0no-custom\x1ftrue"
+# Use markup
+echo -e "\0markup-rows\x1ftrue"
+
+if [ -z "${selection+x}" ]
+then
+ echo -e "\0prompt\x1f ⏻ power "
+ for entry in "${show[@]}"
+ do
+ echo -e "${messages[$entry]}\0icon\x1f${icons[$entry]}"
+ done
+else
+ for entry in "${show[@]}"
+ do
+ if [ "$selection" = "$(print_selection "${messages[$entry]}")" ]
+ then
+ # Check if the selected entry is listed in confirmation requirements
+ for confirmation in "${confirmations[@]}"
+ do
+ if [ "$entry" = "$confirmation" ]
+ then
+ # Ask for confirmation
+ echo -e "\0prompt\x1fAre you sure"
+ echo -e "${confirmationMessages[$entry]}\0icon\x1f${icons[$entry]}"
+ echo -e "${confirmationMessages[cancel]}\0icon\x1f${icons[cancel]}"
+ exit 0
+ fi
+ done
+ # If not, then no confirmation is required, so mark confirmed
+ selection=$(print_selection "${confirmationMessages[$entry]}")
+ fi
+ if [ "$selection" = "$(print_selection "${confirmationMessages[$entry]}")" ]
+ then
+ if [ $dryrun = true ]
+ then
+ # Tell what would have been done
+ echo "Selected: $entry" >&2
+ else
+ # Perform the action
+ ${actions[$entry]}
+ fi
+ exit 0
+ fi
+ if [ "$selection" = "$(print_selection "${confirmationMessages[cancel]}")" ]
+ then
+ # Do nothing
+ exit 0
+ fi
+ done
+ # The selection didn't match anything, so raise an error
+ echo "Invalid selection: $selection" >&2
+ exit 1
+fi
diff --git a/.config/sxhkd/sxhkdrc b/.config/sxhkd/sxhkdrc
index acb7cbc..a43ab5c 100644
--- a/.config/sxhkd/sxhkdrc
+++ b/.config/sxhkd/sxhkdrc
@@ -14,6 +14,9 @@ super + d
super + v
~/.config/rofi/scripts/vim-cheat.sh
+# power menu
+super + p
+ rofi -show p -modi p:'~/.config/rofi/scripts/rofi-power-menu --symbols-font "JetBrainsMonoNL Nerd Font Mono"' -font "JetBrainsMonoNL Nerd Font Mono" -monitor -1
# print screen
Print
path="$HOME/pictures/screenshots/$(date +"%s - %Y-%m-%d")" && maim "$path" && xclip -selection clipboard -t image/png "$path"