Fixing YT blocking and browser setup. - dotfiles - These are my dotfiles. There are many like it, but these are mine.
 (HTM) git clone git://jay.scot/dotfiles
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
       ---
 (DIR) commit b8e22accd07e63bdd8c6c82136312268bb37f9b3
 (DIR) parent 7b3c1c38ea8f8bbe950e06903fbfa6a271b16252
 (HTM) Author: Jay Scott <me@jay.scot>
       Date:   Wed,  6 Aug 2025 13:40:01 +0100
       
       Fixing YT blocking and browser setup.
       
       Diffstat:
         M README                              |       4 ++--
         M ashrc                               |       4 ++--
         D bin/ytd                             |      73 -------------------------------
         M bootstrap.sh                        |       2 +-
         M isync/mbsyncrc                      |       2 +-
         M mutt/muttrc                         |       7 +++++++
         M newsraft/config                     |       3 +++
         M newsraft/feeds                      |      36 ++++++++-----------------------
         M qutebrowser/config.py               |      14 ++++++++++----
         A qutebrowser/userscripts/password_f… |     388 ++++++++++++++++++++++++++++++
         M sway/config                         |       3 ++-
         M waybar/config                       |      25 ++++++++++++++++++++++++-
         M waybar/style.css                    |      14 ++++++++++++--
         A waybar/waybar_newsraft.sh           |      11 +++++++++++
       
       14 files changed, 472 insertions(+), 114 deletions(-)
       ---
 (DIR) diff --git a/README b/README
       @@ -17,9 +17,9 @@ my main desktop OS and are forever evolving.
          terminal       : foot
          launcher       : bemenu
          email          : neomutt
       -  browser        : firefox / lynx
       +  browser        : librewolf / lynx
          media          : kew / mpv
       -  password mgmt  : gopass
       +  password mgmt  : pass
          vpn            : mullvad
          news           : newsraft
        
 (DIR) diff --git a/ashrc b/ashrc
       @@ -10,7 +10,7 @@ export PASSWORD_STORE_DIR="$XDG_CONFIG_HOME"/pass
        GPG_TTY=$(tty)
        export GPG_TTY
        export EDITOR="nvim"
       -export BROWSER="librewolf"
       +export BROWSER="qutebrowser"
        export PATH=$PATH:$HOME/bin
        
        # tools
       @@ -43,7 +43,7 @@ alias mutt='neomutt'
        alias mpv="mpv --autofit=30% --really-quiet --no-terminal"
        
        # vpn
       -alias von='doas wg-quick up se-sto-wg-011'
       +alias von='doas resolvconf -u && doas wg-quick up se-sto-wg-011'
        alias voff='doas wg-quick down se-sto-wg-011'
        alias vcheck='curl https://am.i.mullvad.net/connected'
        
 (DIR) diff --git a/bin/ytd b/bin/ytd
       @@ -1,73 +0,0 @@
       -#!/bin/sh
       -
       -# yt-dlp subscription fetcher
       -# jay <me@jay.scot>
       -
       -savepath="$HOME/media/youtube"
       -cachedir="$HOME/.cache/yt_dl"
       -yt="yt-dlp"
       -baseurl="https://www.youtube.com/playlist?list="
       -
       -info() {
       -        printf "\033[35mYT ➤\033[36m %s\033[0m\n" "$1"
       -}
       -
       -main() {
       -        mkdir -p "${cachedir}"
       -        mkdir -p "${savepath}"
       -
       -        action="$1"
       -        "$action" "steve1989mreinfo" "UU2I6Et1JkidnnbWgJFiMeHA"
       -        "$action" "dave_snider" "UU7uO9V1Frl_wPd9d1qOm_RQ"
       -        "$action" "bright_sun_films" "UU5k3Kc0avyDJ2nG9Kxm9JmQ"
       -        "$action" "simon_wilson" "UUQCrKxBj5Id79syQEsY2Qxg"
       -        "$action" "sidenote" "UURvWwMPr2SmSG7rXXzeEUdA"
       -        "$action" "c90adventures" "UUVqpNG1R72i21jh-nAxEk4A"
       -        "$action" "indigo_traveller" "UUXulruMI7BHj3kGyosNa0jA"
       -        "$action" "pppeter" "UUnHEz9DZ6EAof1-DaQGD_Xw"
       -        "$action" "abroad_in_japan" "UUHL9bfHTxCMi-7vfxQ-AYtg"
       -        "$action" "serpentza" "UUl7mAGnY4jh4Ps8rhhh8XZg"
       -        "$action" "noel_phillips" "UU2O6HDtMOZf9FkUAepz9Atg"
       -        "$action" "the_lazy_peon" "UUE-f0sqi-H7kuLT0YiW9rcA"
       -        "$action" "zav_alsop" "UUcjx6m03fZwtRBFn1Cf7kKQ"
       -        "$action" "steve_marsh" "UUBhQuxcHU3aydk_zTXcbdTg"
       -        "$action" "planes_trains_everything" "UUcKw8Eg0FfRvhIAnC0cPGAA"
       -        "$action" "we_hate_the_cold" "UULmltEyJ0zBsKnL8bWSdn3A"
       -        "$action" "christopher_collects" "UUv8Po8UR9OfhPhPCLjz1d8Q"
       -        "$action" "astonishing_glasgow" "UUIDIqg7LhjLFCyD2awY_38g"
       -        "$action" "mike_okay" "UUpp3cHR9TWVyXqL1AVw4XkA"
       -        "$action" "all_the_gear" "UUSwl4SnA68L8iDfj5gBf-yA"
       -        "$action" "rhykker" "UURl31PWkfF0a3j3hiDRaCGA"
       -        "$action" "brodie_robertson" "UUld68syR8Wi-GY_n4CaoJGA"
       -        "$action" "distrotube" "UUVls1GmFKf6WlTraIb_IaJg"
       -        "$action" "linux_cast" "UUylGUf9BvQooEFjgdNudoQg"
       -}
       -
       -get_video() {
       -        info "Fetching latest from $1"
       -        mkdir -p "${savepath}/${1}"
       -
       -        "$yt" -q --restrict-filename \
       -                --download-archive "${cachedir}/${1}" \
       -                "${baseurl}${2}" \
       -                -o "${savepath}/${1}/%(playlist_index)s_%(title)s.%(ext)s" \
       -                --cookies ~/tmp/cookies.txt
       -}
       -
       -catchup() {
       -        info "Catching up on $1"
       -        "$yt" --flat-playlist --get-id \
       -                "${baseurl}${2}" | sed 's/.*/youtube &/' >"${cachedir}/${1}"
       -}
       -
       -case "$1" in
       --m)
       -        main catchup
       -        ;;
       --n)
       -        catchup "$2" "$3"
       -        ;;
       -*)
       -        main get_video
       -        ;;
       -esac
 (DIR) diff --git a/bootstrap.sh b/bootstrap.sh
       @@ -4,7 +4,7 @@ DOTFILES=$(pwd)
        
        FILES='ashrc profile'
        ROOT='bin'
       -CONFIG='foot git isync lynx mutt newsraft nvim sway waybar'
       +CONFIG='foot git isync lynx mutt newsraft nvim qutebrowser sway waybar'
        
        link() {
                for f in $FILES; do ln -sfn "$DOTFILES/$f" "$HOME/.$f"; done
 (DIR) diff --git a/isync/mbsyncrc b/isync/mbsyncrc
       @@ -7,7 +7,7 @@ SyncState *
        IMAPAccount jay
        Host imap.mailbox.org
        User me@jay.scot
       -PassCmd "gopass show -o tech/mailbox.org"
       +PassCmd "pass show tech/smtp.mailbox.org"
        TLSType IMAPS
        
        IMAPStore jay-remote
 (DIR) diff --git a/mutt/muttrc b/mutt/muttrc
       @@ -3,6 +3,8 @@ source ~/.config/mutt/gruvbox
        # info
        set realname        = 'Jay Scott'
        set from                = 'me@jay.scot'
       +set my_user                = 'me@jay.scot'
       +set my_pass                = "`pass tech/smtp.mailbox.org`"
        
        # general
        set envelope_from        = yes
       @@ -48,6 +50,11 @@ set record      = "+jay/Sent"
        # inbox
        mailboxes ! `echo ~/.mail/jay/*`
        
       +# SMTP settings
       +set smtp_pass                 = $my_pass
       +set smtp_url                = smtps://$my_user@smtp.mailbox.org
       +set ssl_force_tls         = yes
       +
        # aliases
        set alias_file                = ~/.config/mutt/aliases
        set sort_alias                = alias
 (DIR) diff --git a/newsraft/config b/newsraft/config
       @@ -5,3 +5,6 @@ feeds-menu-paramount-explore true
        
        # key bindings
        bind f exec "~/bin/link-handler %l"
       +
       +# appearance
       +status-placeholder
 (DIR) diff --git a/newsraft/feeds b/newsraft/feeds
       @@ -21,30 +21,12 @@ https://www.jeffgeerling.com/blog.xml "Jeff Geerling"
        @ GAMING
        https://www.gamingonlinux.com/article_rss.php "Gaming On Linux"
        
       -#@ YOUTUBE
       -#https://www.youtube.com/feeds/videos.xml?channel_id=UC2I6Et1JkidnnbWgJFiMeHA "Steve1989MREInfo"
       -#https://www.youtube.com/feeds/videos.xml?channel_id=UC7uO9V1Frl_wPd9d1qOm_RQ "Dave Snider"
       -#https://www.youtube.com/feeds/videos.xml?channel_id=UC5k3Kc0avyDJ2nG9Kxm9JmQ "Bright Sun Films"
       -#https://www.youtube.com/feeds/videos.xml?channel_id=UCQCrKxBj5Id79syQEsY2Qxg "Simon Wilson"
       -#https://www.youtube.com/feeds/videos.xml?channel_id=UCRvWwMPr2SmSG7rXXzeEUdA "SideNote"
       -#https://www.youtube.com/feeds/videos.xml?channel_id=UCVqpNG1R72i21jh-nAxEk4A "c90adventures"
       -#https://www.youtube.com/feeds/videos.xml?channel_id=UCXulruMI7BHj3kGyosNa0jA "Indigo Traveller"
       -#https://www.youtube.com/feeds/videos.xml?channel_id=UCnHEz9DZ6EAof1-DaQGD_Xw "PPPeter"
       -#https://www.youtube.com/feeds/videos.xml?channel_id=UCHL9bfHTxCMi-7vfxQ-AYtg "Abroad in Japan"
       -#https://www.youtube.com/feeds/videos.xml?channel_id=UCl7mAGnY4jh4Ps8rhhh8XZg "Serpentza"
       -#https://www.youtube.com/feeds/videos.xml?channel_id=UC2O6HDtMOZf9FkUAepz9Atg "Noel Phillips"
       -#https://www.youtube.com/feeds/videos.xml?channel_id=UCE-f0sqi-H7kuLT0YiW9rcA "The Lazy Peon"
       -#https://www.youtube.com/feeds/videos.xml?channel_id=UCcjx6m03fZwtRBFn1Cf7kKQ "Zav Alsop"
       -#https://www.youtube.com/feeds/videos.xml?channel_id=UCBhQuxcHU3aydk_zTXcbdTg "Steve Marsh"
       -#https://www.youtube.com/feeds/videos.xml?channel_id=UCcKw8Eg0FfRvhIAnC0cPGAA "Planes, Trains, Everything"
       -#https://www.youtube.com/feeds/videos.xml?channel_id=UCLmltEyJ0zBsKnL8bWSdn3A "We Hate The Cold"
       -#https://www.youtube.com/feeds/videos.xml?channel_id=UCv8Po8UR9OfhPhPCLjz1d8Q "Christopher Collects"
       -#https://www.youtube.com/feeds/videos.xml?channel_id=UCIDIqg7LhjLFCyD2awY_38g "Astonishing Glasgow"
       -#https://www.youtube.com/feeds/videos.xml?channel_id=UC7sGXeJOixPBgJ3r5R55JYg "Drain Cleaning Aus"
       -#https://www.youtube.com/feeds/videos.xml?channel_id=UCpp3cHR9TWVyXqL1AVw4XkA "Mike Okay"
       -#https://www.youtube.com/feeds/videos.xml?channel_id=UCSwl4SnA68L8iDfj5gBf-yA "All the Gear"
       -#https://www.youtube.com/feeds/videos.xml?channel_id=UCRl31PWkfF0a3j3hiDRaCGA "Rhykker"
       -#https://www.youtube.com/feeds/videos.xml?channel_id=UCsxidPdmPXDlsS3rn7arJsA "Signs Of Kelani"
       -#https://www.youtube.com/feeds/videos.xml?channel_id=UCld68syR8Wi-GY_n4CaoJGA "Brodie Robertson"
       -#https://www.youtube.com/feeds/videos.xml?channel_id=UCVls1GmFKf6WlTraIb_IaJg "DistroTube"
       -#https://www.youtube.com/feeds/videos.xml?channel_id=UCylGUf9BvQooEFjgdNudoQg "Linux Cast"
       +@ ODYSEE
       +https://odysee.com/$/rss/@AlphaNerd:8 "Mental Outlaw"
       +https://odysee.com/$/rss/@DistroTube:2 "DistroTube"
       +https://odysee.com/$/rss/@techlore:3 "TechLore"
       +https://odysee.com/$/rss/@NaomiBrockwell:4 "Naomi Brockwell"
       +https://odysee.com/$/rss/@BrodieRobertson:5 "Brodie Robertson"
       +https://odysee.com/$/rss/@davidbombal:0 "David Bombal"
       +https://odysee.com/$/rss/@thelinuxcast:4 "The Linux Cast"
       +https://odysee.com/$/rss/@GreatScott:a "Great Scott"
 (DIR) diff --git a/qutebrowser/config.py b/qutebrowser/config.py
       @@ -31,8 +31,13 @@ c.tabs.favicons.show = "never"
        # hints
        c.colors.hints.bg = "rgb(207,186,88)" #cfba58
        c.colors.hints.fg = "rgb(34, 34, 34)" #222222
       -c.colors.webpage.darkmode.enabled = False
       -c.colors.webpage.darkmode.algorithm = "lightness-hsl"
       +
       +# darkmode
       +c.colors.webpage.darkmode.enabled = True
       +#c.colors.webpage.darkmode.algorithm = "lightness-hsl"
       +c.colors.webpage.darkmode.algorithm = 'lightness-cielab'
       +c.colors.webpage.darkmode.policy.images = 'never'
       +config.set('colors.webpage.darkmode.enabled', False, 'file://*')
        
        # misc
        c.fonts.hints = "10pt Hack"
       @@ -42,6 +47,7 @@ c.hints.uppercase = True
        c.scrolling.smooth = True
        c.editor.command = ["alacritty", "vim '{}'"]
        c.auto_save.session = True
       +c.zoom.default = "140%"
        
        # ad-block
        c.content.blocking.enabled = True
       @@ -74,14 +80,14 @@ c.content.autoplay = False # no autoplay on <video> tags
        c.content.headers.accept_language = "en-US,en;q=0.5"
        c.content.headers.user_agent = "Mozilla/5.0 (X11; Linux i686; rv:109.0) Gecko/20100101 Firefox/120.0"
        c.content.headers.custom = {"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"}
       -c.content.headers.referer = "same-domain"
       +c.content.headers.referer = "never"
        c.content.cookies.accept = "no-3rdparty"
        c.content.javascript.enabled = False # disable tracking etc
        c.content.canvas_reading = False # canvas blocking
        c.content.geolocation = False # location ident
        c.content.webrtc_ip_handling_policy = "disable-non-proxied-udp"
        c.content.hyperlink_auditing = False # disable pingbacks
       -c.content.dns_prefetch = False # disable pre-fetching
       +c.content.dns_prefetch = False # disable dns pre-fetching
        
        # search engine shortneners
        c.url.searchengines = {
 (DIR) diff --git a/qutebrowser/userscripts/password_fill b/qutebrowser/userscripts/password_fill
       @@ -0,0 +1,388 @@
       +#!/usr/bin/env bash
       +help() {
       +    blink=$'\e[1;31m' reset=$'\e[0m'
       +cat <<EOF
       +This script can only be used as a userscript for qutebrowser
       +2015, Thorsten Wißmann <edu _at_ thorsten-wissmann _dot_ de>
       +In case of questions or suggestions, do not hesitate to send me an E-Mail or to
       +directly ask me via IRC (nickname thorsten\`) in #qutebrowser on Libera Chat.
       +
       +  $blink!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!$reset
       +  WARNING: the passwords are stored in qutebrowser's
       +           debug log reachable via the url qute://log
       +  $blink!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!$reset
       +
       +Usage: run as a userscript form qutebrowser, e.g.:
       +  spawn --userscript ~/.config/qutebrowser/password_fill
       +
       +Pass backend: (see also passwordstore.org)
       +  This script expects pass to store the credentials of each page in an extra
       +  file, where the filename (or filepath) contains the domain of the respective
       +  page. The first line of the file must contain the password, the login name
       +  must be contained in a later line beginning with "user:", "login:", or
       +  "username:" (configurable by the user_pattern variable).
       +
       +Behavior:
       +  It will try to find a username/password entry in the configured backend
       +  (currently only pass) for the current website and will load that pair of
       +  username and password to any form on the current page that has some password
       +  entry field. If multiple entries are found, a zenity menu is offered.
       +
       +  If no entry is found, then it crops subdomains from the url if at least one
       +  entry is found in the backend. (In that case, it always shows a menu)
       +
       +Configuration:
       +  This script loads the bash script ~/.config/qutebrowser/password_fill_rc (if
       +  it exists), so you can change any configuration variable and overwrite any
       +  function you like.
       +
       +EOF
       +}
       +
       +set -o errexit
       +set -o pipefail
       +shopt -s nocasematch # make regexp matching in bash case insensitive
       +
       +if [ -z "$QUTE_FIFO" ] ; then
       +    help
       +    exit
       +fi
       +
       +error() {
       +    local msg="$*"
       +    echo "message-error '${msg//\'/\\\'}'" >> "$QUTE_FIFO"
       +}
       +msg() {
       +    local msg="$*"
       +    echo "message-info '${msg//\'/\\\'}'" >> "$QUTE_FIFO"
       +}
       +die() {
       +    error "$*"
       +    exit 0
       +}
       +
       +javascript_escape() {
       +    # print the first argument in an escaped way, such that it can safely
       +    # be used within javascripts double quotes
       +    # shellcheck disable=SC2001
       +    sed "s,[\\\\'\"],\\\\&,g" <<< "$1"
       +}
       +
       +# ======================================================= #
       +# CONFIGURATION
       +# ======================================================= #
       +# The configuration file is per default located in
       +# ~/.config/qutebrowser/password_fill_rc and is a bash script that is loaded
       +# later in the present script. So basically you can replace all of the
       +# following definitions and make them fit your needs.
       +
       +# The following simplifies a URL to the domain (e.g. "wiki.qutebrowser.org")
       +# which is later used to search the correct entries in the password backend. If
       +# you e.g. don't want the "www." to be removed or if you want to distinguish
       +# between different paths on the same domain.
       +
       +simplify_url() {
       +    simple_url="${1##*://}" # remove protocol specification
       +    simple_url="${simple_url%%\?*}" # remove GET parameters
       +    simple_url="${simple_url%%/*}" # remove directory path
       +    simple_url="${simple_url%:*}" # remove port
       +    simple_url="${simple_url##www.}" # remove www. subdomain
       +}
       +
       +# no_entries_found() is called if the first query_entries() call did not find
       +# any matching entries. Multiple implementations are possible:
       +# The easiest behavior is to quit:
       +#no_entries_found() {
       +#    if [ 0 -eq "${#files[@]}" ] ; then
       +#        die "No entry found for »$simple_url«"
       +#    fi
       +#}
       +# But you could also fill the files array with all entries from your pass db
       +# if the first db query did not find anything
       +# no_entries_found() {
       +#     if [ 0 -eq "${#files[@]}" ] ; then
       +#         query_entries ""
       +#         if [ 0 -eq "${#files[@]}" ] ; then
       +#             die "No entry found for »$simple_url«"
       +#         fi
       +#     fi
       +# }
       +
       +# Another behavior is to drop another level of subdomains until search hits
       +# are found:
       +no_entries_found() {
       +    while [ 0 -eq "${#files[@]}" ] && [ -n "$simple_url" ]; do
       +        # shellcheck disable=SC2001
       +        shorter_simple_url=$(sed 's,^[^.]*\.,,' <<< "$simple_url")
       +        if [ "$shorter_simple_url" = "$simple_url" ] ; then
       +            # if no dot, then even remove the top level domain
       +            simple_url=""
       +            query_entries "$simple_url"
       +            break
       +        fi
       +        simple_url="$shorter_simple_url"
       +        query_entries "$simple_url"
       +        #die "No entry found for »$simple_url«"
       +        # enforce menu if we do "fuzzy" matching
       +        menu_if_one_entry=1
       +    done
       +    if [ 0 -eq "${#files[@]}" ] ; then
       +        die "No entry found for »$simple_url«"
       +    fi
       +}
       +
       +# Backend implementations tell, how the actual password store is accessed.
       +# Right now, there is only one fully functional password backend, namely for
       +# the program "pass".
       +# A password backend consists of three actions:
       +#  - init() initializes backend-specific things and does sanity checks.
       +#  - query_entries() is called with a simplified url and is expected to fill
       +#    the bash array $files with the names of matching password entries. There
       +#    are no requirements how these names should look like.
       +#  - open_entry() is called with some specific entry of the $files array and is
       +#    expected to write the username of that entry to the $username variable and
       +#    the corresponding password to $password
       +
       +# shellcheck disable=SC2329
       +reset_backend() {
       +    init() { true ; }
       +    query_entries() { true ; }
       +    open_entry() { true ; }
       +}
       +
       +# choose_entry() is expected to choose one entry from the array $files and
       +# write it to the variable $file.
       +choose_entry() {
       +    choose_entry_zenity
       +}
       +
       +# The default implementation chooses a random entry from the array. So if there
       +# are multiple matching entries, multiple calls to this userscript will
       +# eventually pick the "correct" entry. I.e. if this userscript is bound to
       +# "zl", the user has to press "zl" until the correct username shows up in the
       +# login form.
       +choose_entry_random() {
       +    local nr=${#files[@]}
       +    file="${files[$((RANDOM % nr))]}"
       +    # Warn user, that there might be other matching password entries
       +    if [ "$nr" -gt 1 ] ; then
       +        msg "Picked $file out of $nr entries: ${files[*]}"
       +    fi
       +}
       +
       +# another implementation would be to ask the user via some menu (like rofi or
       +# dmenu or zenity or even qutebrowser completion in future?) which entry to
       +# pick
       +MENU_COMMAND=( head -n 1 )
       +# whether to show the menu if there is only one entry in it
       +menu_if_one_entry=0
       +choose_entry_menu() {
       +    local nr=${#files[@]}
       +    if [ "$nr" -eq 1 ] && ! ((menu_if_one_entry)) ; then
       +        file="${files[0]}"
       +    else
       +        file=$( printf '%s\n' "${files[@]}" | "${MENU_COMMAND[@]}" )
       +    fi
       +}
       +
       +choose_entry_rofi() {
       +    MENU_COMMAND=( rofi -p "qutebrowser> " -dmenu
       +                        -mesg $'Pick a password entry for <b>'"${QUTE_URL//&/&amp;}"'</b>' )
       +    choose_entry_menu || true
       +}
       +
       +choose_entry_zenity() {
       +    MENU_COMMAND=( zenity --list --title "qutebrowser password fill"
       +                          --text "Pick the password entry:"
       +                          --column "Name" )
       +    choose_entry_menu || true
       +}
       +
       +choose_entry_zenity_radio() {
       +    # shellcheck disable=SC2329
       +    zenity_helper() {
       +        awk '{ print $0 ; print $0 }'                   \
       +        | zenity --list --radiolist                     \
       +                 --title "qutebrowser password fill"    \
       +                 --text "Pick the password entry:"      \
       +                 --column " " --column "Name"
       +    }
       +    MENU_COMMAND=( zenity_helper )
       +    choose_entry_menu || true
       +}
       +
       +# =======================================================
       +# backend: PASS
       +
       +# configuration options:
       +match_filename=1 # whether allowing entry match by filepath
       +match_line=0     # whether allowing entry match by URL-Pattern in file
       +                 # Note: match_line=1 gets very slow, even for small password stores!
       +match_line_pattern='^url: .*' # applied using grep -iE
       +user_pattern='^(user|username|login): '
       +
       +GPG_OPTS=( "--quiet" "--yes" "--compress-algo=none" "--no-encrypt-to" )
       +GPG="gpg"
       +export GPG_TTY="${GPG_TTY:-$(tty 2>/dev/null)}"
       +command -v gpg2 &>/dev/null && GPG="gpg2"
       +[[ -n $GPG_AGENT_INFO || $GPG == "gpg2" ]] && GPG_OPTS+=( "--batch" "--use-agent" )
       +
       +pass_backend() {
       +    init() {
       +        PREFIX="${PASSWORD_STORE_DIR:-$HOME/.password-store}"
       +        if ! [ -d "$PREFIX" ] ; then
       +            die "Can not open password store dir »$PREFIX«"
       +        fi
       +    }
       +    query_entries() {
       +        local url="$1"
       +
       +        if ((match_line)) ; then
       +            # add entries with matching URL-tag
       +            while read -r -d "" passfile ; do
       +                if $GPG "${GPG_OPTS[@]}" -d "$passfile" \
       +                     | grep --max-count=1 -iE "${match_line_pattern}${url}" > /dev/null
       +                then
       +                    passfile="${passfile#"$PREFIX"}"
       +                    passfile="${passfile#/}"
       +                    files+=( "${passfile%.gpg}" )
       +                fi
       +            done < <(find -L "$PREFIX" -iname '*.gpg' -print0)
       +        fi
       +        if ((match_filename)) ; then
       +            # add entries with matching filepath
       +            while read -r passfile ; do
       +                passfile="${passfile#"$PREFIX"}"
       +                passfile="${passfile#/}"
       +                files+=( "${passfile%.gpg}" )
       +            done < <(find -L "$PREFIX" -iname '*.gpg' | grep "$url")
       +        fi
       +    }
       +    open_entry() {
       +        local path="$PREFIX/${1}.gpg"
       +        password=""
       +        local firstline=1
       +        while read -r line ; do
       +            if ((firstline)) ; then
       +                password="$line"
       +                firstline=0
       +            else
       +                if [[ $line =~ $user_pattern ]] ; then
       +                    # remove the matching prefix "user: " from the beginning of the line
       +                    username=${line#"${BASH_REMATCH[0]}"}
       +                    break
       +                fi
       +            fi
       +        done < <($GPG "${GPG_OPTS[@]}" -d "$path" | awk 1 )
       +    }
       +}
       +# =======================================================
       +
       +# =======================================================
       +# backend: secret
       +# shellcheck disable=SC2329
       +secret_backend() {
       +    init() {
       +        return
       +    }
       +    query_entries() {
       +        local domain="$1"
       +        while read -r line ; do
       +            if [[ "$line" == "attribute.username = "* ]] ; then
       +                files+=("$domain ${line:21}")
       +            fi
       +        done < <( secret-tool search --unlock --all domain "$domain" 2>&1 )
       +    }
       +    open_entry() {
       +        local domain="${1%% *}"
       +        username="${1#* }"
       +        password=$(secret-tool lookup domain "$domain" username "$username")
       +    }
       +}
       +# =======================================================
       +
       +# load some sane default backend
       +reset_backend
       +pass_backend
       +# load configuration
       +QUTE_CONFIG_DIR=${QUTE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/qutebrowser/}
       +PWFILL_CONFIG=${PWFILL_CONFIG:-${QUTE_CONFIG_DIR}/password_fill_rc}
       +if [ -f "$PWFILL_CONFIG" ] ; then
       +    # shellcheck source=/dev/null
       +    source "$PWFILL_CONFIG"
       +fi
       +init
       +
       +simplify_url "$QUTE_URL"
       +query_entries "${simple_url}"
       +no_entries_found
       +# remove duplicates
       +mapfile -t files < <(printf '%s\n' "${files[@]}" | sort | uniq )
       +choose_entry
       +if [ -z "$file" ] ; then
       +    # choose_entry didn't want any of these entries
       +    exit 0
       +fi
       +open_entry "$file"
       +#username="$(date)"
       +#password="XYZ"
       +#msg "$username, ${#password}"
       +
       +[ -n "$username" ] || die "Username not set in entry $file"
       +[ -n "$password" ] || die "Password not set in entry $file"
       +
       +js() {
       +cat <<EOF
       +    function isVisible(elem) {
       +        var style = elem.ownerDocument.defaultView.getComputedStyle(elem, null);
       +
       +        if (style.getPropertyValue("visibility") !== "visible" ||
       +            style.getPropertyValue("display") === "none" ||
       +            style.getPropertyValue("opacity") === "0") {
       +            return false;
       +        }
       +
       +        return elem.offsetWidth > 0 && elem.offsetHeight > 0;
       +    };
       +    function hasPasswordField(form) {
       +        var inputs = form.getElementsByTagName("input");
       +        for (var j = 0; j < inputs.length; j++) {
       +            var input = inputs[j];
       +            if (input.type == "password") {
       +                return true;
       +            }
       +        }
       +        return false;
       +    };
       +    function loadData2Form (form) {
       +        var inputs = form.getElementsByTagName("input");
       +        for (var j = 0; j < inputs.length; j++) {
       +            var input = inputs[j];
       +            if (isVisible(input) && (input.type == "text" || input.type == "email")) {
       +                input.focus();
       +                input.value = "$(javascript_escape "${username}")";
       +                input.dispatchEvent(new Event('change'));
       +                input.blur();
       +            }
       +            if (input.type == "password") {
       +                input.focus();
       +                input.value = "$(javascript_escape "${password}")";
       +                input.dispatchEvent(new Event('change'));
       +                input.blur();
       +            }
       +        }
       +    };
       +
       +    var forms = document.getElementsByTagName("form");
       +    for (i = 0; i < forms.length; i++) {
       +        if (hasPasswordField(forms[i])) {
       +            loadData2Form(forms[i]);
       +        }
       +    }
       +EOF
       +}
       +
       +printjs() {
       +    js | sed 's,//.*$,,' | tr '\n' ' '
       +}
       +echo "jseval -q $(printjs)" >> "$QUTE_FIFO"
 (DIR) diff --git a/sway/config b/sway/config
       @@ -18,6 +18,7 @@ font pango: Hack:style=Regular 2
        # application assignment
        #for_window [app_id="mpv"] floating enable, sticky enable, resize set 560 280, move absolute position 3000 1100, no_focus
        assign [app_id="librewolf"] 2
       +assign [app_id="qutebrowser"] 2
        
        # misc
        xwayland enable
       @@ -49,7 +50,7 @@ focus output DP-1
        # keybinds
        bindsym $mod+Space exec footclient
        bindsym $mod+p exec $menu
       -bindsym $mod+f exec librewolf
       +bindsym $mod+f exec qutebrowser
        bindsym $mod+m exec /home/jay/bin/music
        bindsym $mod+s exec flatpak run com.heroicgameslauncher.hgl
        
 (DIR) diff --git a/waybar/config b/waybar/config
       @@ -15,6 +15,8 @@
                ],
        
                "modules-right": [
       +                "custom/newsraft",
       +                "custom/mail",
                        "pulseaudio",
                        "tray",
                        "clock"
       @@ -54,7 +56,28 @@
                        "exec": "$HOME/.config/waybar/waybar_vpn.sh"
                },
        
       +        "custom/mail": {
       +                "format": "{icon}",
       +                "format-icons": {
       +                        "default": ["🖂"]
       +                },
       +                "return-type": "json",
       +                "interval": 60,
       +                "exec": "$HOME/.config/waybar/waybar_mail.sh"
       +        },
       +
       +        "custom/newsraft": {
       +                "format": "{icon}",
       +                "format-icons": {
       +                        "default": ["💩"]
       +                },
       +                "return-type": "json",
       +                "interval": 60,
       +                "exec": "$HOME/.config/waybar/waybar_newsraft.sh"
       +        },
       +
                "tray": {
       -                "icon-size": 12
       +                "icon-size": 16,
       +                "spacing": 10
                }
        }
 (DIR) diff --git a/waybar/style.css b/waybar/style.css
       @@ -1,5 +1,5 @@
        * {
       -        font-size: 12px;
       +        font-size: 16px;
                font-family: Hack;
        }
        
       @@ -25,8 +25,18 @@ window#waybar {
                color: #d22635;
        }
        
       +#custom-mail.new {
       +        color: #268bd2;
       +}
       +
       +#custom-newsraft.new {
       +        color: #268bd2;
       +}
       +
        #clock,
        #custom-vpn,
       +#custom-mail,
       +#custom-newsraft,
        #pulseaudio {
       -        padding: 0 3px;
       +        padding: 0 5px;
        }
 (DIR) diff --git a/waybar/waybar_newsraft.sh b/waybar/waybar_newsraft.sh
       @@ -0,0 +1,11 @@
       +#!/bin/sh
       +
       +new="$(newsraft -e print-unread-items-count)"
       +
       +if [ $new -gt 0 ]
       +then
       +        echo "{\"text\":\"$new\",\"tooltip\":\"$new articles\",\"class\":\"new\"}"
       +else
       +        echo '{"text":"No new articles","tooltip":"","class":""}'
       +fi
       +