diff --git a/arch_news.sh b/arch_news.sh
new file mode 100755
index 0000000..8aaadb7
--- /dev/null
+++ b/arch_news.sh
@@ -0,0 +1,254 @@
+#!/bin/bash
+
+# Arch Linux News Notifier
+# Fetches latest news from Arch Linux RSS feed and shows notifications for new items
+
+# Configuration
+RSS_URL="https://archlinux.org/feeds/news/"
+CACHE_FILE="$HOME/.cache/arch-news-seen"
+TEMP_FILE="/tmp/arch-news-latest"
+
+ICON_NORMAL="/usr/share/pixmaps/tabler--coffee.svg"
+ICON_URGENT="/usr/share/pixmaps/charm--circle-warning.svg"
+
+# Create cache directory if it doesn't existnClick to open:
+mkdir -p "$(dirname "$CACHE_FILE")"
+
+# Function to extract and format news items
+parse_rss() {
+ # Debug: show what we're working with
+ if [[ "$DEBUG" == "1" ]]; then
+ echo "=== DEBUG: RSS file content preview ===" >&2
+ head -20 "$TEMP_FILE" >&2
+ echo "=== END DEBUG ===" >&2
+ fi
+
+ if command -v xmllint >/dev/null 2>&1; then
+ # Use xmllint to extract items properly
+ xmllint --xpath "//item[position()<=5]" "$TEMP_FILE" 2>/dev/null |
+ sed 's|- |\n
- |g' |
+ sed 's|
| \n|g' |
+ grep -A 20 '- ' |
+ awk -v RS='
' '
+ /- / {
+ title = ""; link = ""; pubdate = ""
+
+ # Extract title
+ if (match($0, /]*>([^<]*)<\/title>/, arr)) {
+ title = arr[1]
+ gsub(/>/, ">", title)
+ gsub(/</, "<", title)
+ gsub(/&/, "&", title)
+ }
+
+ # Extract link (not atom:link)
+ if (match($0, /([^<]*)<\/link>/, arr)) {
+ link = arr[1]
+ }
+
+ # Extract pubDate
+ if (match($0, /([^<]*)<\/pubDate>/, arr)) {
+ pubdate = arr[1]
+ }
+
+ if (title && link && pubdate) {
+ print pubdate "|" title "|" link
+ }
+ }'
+ else
+ # Fallback: simple grep approach
+ local temp_items="/tmp/arch-items-$"
+
+ # Extract each item block
+ awk '/
- /,/<\/item>/' "$TEMP_FILE" >"$temp_items"
+
+ # Process with simple pattern matching
+ while IFS= read -r line; do
+ if [[ "$line" =~ \([^<]*)\ ]]; then
+ title="${BASH_REMATCH[1]}"
+ title="${title//>/>}"
+ title="${title//</<}"
+ title="${title//&/&}"
+ elif [[ "$line" =~ \([^<]*)\ ]] && [[ ! "$line" =~ atom:link ]]; then
+ link="${BASH_REMATCH[1]}"
+ elif [[ "$line" =~ \([^<]*)\ ]]; then
+ pubdate="${BASH_REMATCH[1]}"
+
+ # When we have all three, output and reset
+ if [[ -n "$title" && -n "$link" && -n "$pubdate" ]]; then
+ echo "$pubdate|$title|$link"
+ title=""
+ link=""
+ pubdate=""
+ fi
+ fi
+ done <"$temp_items"
+
+ rm -f "$temp_items"
+ fi
+}
+
+# Function to send notification
+send_notification() {
+ local title="$1"
+ local body="$2"
+ local url="$3"
+
+ # Determine urgency level based on content
+ local urgency="normal"
+ local icon=$ICON_NORMAL
+
+ # Check for urgent intervention keywords (case insensitive)
+ if echo "$title $body" | grep -qi "\(manual intervention\|action required\|breaking change\|immediate action\|urgent\|critical\|important.*update\|requires.*intervention\)"; then
+ urgency="critical"
+ icon=$ICON_URGENT
+ fi
+
+ # Send notification with appropriate urgency
+ notify-send \
+ --urgency="$urgency" \
+ --app-name="Arch News" \
+ --icon="$icon" \
+ --expire-time=20000 \
+ "$title" \
+ "$body\n$url"
+
+ # Debug output
+ if [[ "$DEBUG" == "1" ]]; then
+ echo "=== DEBUG: Notification sent ===" >&2
+ echo "Title: $title" >&2
+ echo "Urgency: $urgency" >&2
+ echo "Reason: $(echo "$title $body" | grep -i "\(manual intervention\|action required\|breaking change\|immediate action\|urgent\|critical\|important.*update\|requires.*intervention\)" || echo "normal news")" >&2
+ echo "=== END DEBUG ===" >&2
+ fi
+}
+
+# Main execution
+main() {
+ # Parse command line options
+ local force_show=false
+ local show_latest=false
+
+ while [[ $# -gt 0 ]]; do
+ case $1 in
+ --force)
+ force_show=true
+ shift
+ ;;
+ --show-latest)
+ show_latest=true
+ shift
+ ;;
+ --clear-cache)
+ rm -f "$CACHE_FILE"
+ echo "Cache cleared"
+ exit 0
+ ;;
+ --help | -h)
+ echo "Usage: $0 [options]"
+ echo "Options:"
+ echo " --force Show notifications for latest news even if already seen"
+ echo " --show-latest Show notification for the latest news item only"
+ echo " --clear-cache Clear the seen items cache"
+ echo " --help Show this help message"
+ exit 0
+ ;;
+ *)
+ echo "Unknown option: $1" >&2
+ exit 1
+ ;;
+ esac
+ done
+
+ # Check if required tools are available
+ if ! command -v xmllint >/dev/null 2>&1; then
+ echo "Error: xmllint is required (install libxml2-utils)" >&2
+ exit 1
+ fi
+
+ if ! command -v notify-send >/dev/null 2>&1; then
+ echo "Error: notify-send is required" >&2
+ exit 1
+ fi
+
+ # Fetch RSS feed
+ if ! curl -s --max-time 30 "$RSS_URL" >"$TEMP_FILE"; then
+ echo "Error: Failed to fetch RSS feed" >&2
+ exit 1
+ fi
+
+ # Debug: Check if file was created and has content
+ if [[ "$DEBUG" == "1" ]]; then
+ echo "=== DEBUG: Temp file info ===" >&2
+ ls -la "$TEMP_FILE" >&2
+ echo "First few lines:" >&2
+ head -5 "$TEMP_FILE" >&2
+ echo "=== END DEBUG ===" >&2
+ fi
+
+ # Check if file is not empty
+ if [[ ! -s "$TEMP_FILE" ]]; then
+ echo "Error: RSS feed is empty" >&2
+ exit 1
+ fi
+
+ # Create cache file if it doesn't exist
+ [[ ! -f "$CACHE_FILE" ]] && touch "$CACHE_FILE"
+
+ # Parse RSS and check for new items
+ local new_items=0
+ local items_processed=0
+
+ # Debug: show all parsed items
+ if [[ "$DEBUG" == "1" ]]; then
+ echo "=== DEBUG: All parsed RSS items ===" >&2
+ parse_rss | nl >&2
+ echo "=== END DEBUG ===" >&2
+ fi
+
+ while IFS='|' read -r pubdate title link; do
+ [[ -z "$title" ]] && continue
+ ((items_processed++))
+
+ # Create a unique identifier for this news item
+ local item_id=$(echo "$title$pubdate" | md5sum | cut -d' ' -f1)
+
+ # Show latest item only if requested
+ if [[ "$show_latest" == true && $items_processed -eq 1 ]]; then
+ local formatted_date=$(date -d "$pubdate" "+%d.%m.%Y" 2>/dev/null || echo "Recent")
+ send_notification "$title" "Published: $formatted_date" "$link"
+ echo "$item_id" >>"$CACHE_FILE"
+ ((new_items++))
+ break
+ fi
+
+ # Check if we've already seen this item (or force showing)
+ if [[ "$force_show" == true ]] || ! grep -q "$item_id" "$CACHE_FILE"; then
+ # New item found - send notification
+ local formatted_date=$(date -d "$pubdate" "+%d.%m.%Y" 2>/dev/null || echo "Recent")
+ send_notification "$title" "Published: $formatted_date" "$link"
+
+ # Mark as seen (only if not forcing)
+ if [[ "$force_show" == false ]]; then
+ echo "$item_id" >>"$CACHE_FILE"
+ fi
+ ((new_items++))
+
+ # Add delay between notifications for better mako stacking
+ [[ $new_items -gt 1 ]] && sleep 1.5
+ fi
+ done < <(parse_rss)
+
+ # Clean up
+ rm -f "$TEMP_FILE"
+
+ # Limit cache file size (keep last 100 entries)
+ if [[ -f "$CACHE_FILE" ]]; then
+ tail -100 "$CACHE_FILE" >"$CACHE_FILE.tmp" && mv "$CACHE_FILE.tmp" "$CACHE_FILE"
+ fi
+
+ echo "Checked Arch Linux news - $new_items new items found"
+}
+
+# Run main function
+main "$@"
diff --git a/lock b/lock
new file mode 100755
index 0000000..e143482
--- /dev/null
+++ b/lock
@@ -0,0 +1,55 @@
+#!/bin/bash
+# Ayu Dark Theme Colors for i3lock-color
+
+alpha='dd'
+background='#0B0E14' # Ayu dark background
+selection='#1B3A5B' # Ayu selection background
+golden_yellow='#FFB454' # Ayu accent color
+bright_blue='#39BAE6' # Ayu tag color
+orange='#FFB454' # Ayu function color
+light_blue='#59C2FF' # Ayu entity color
+green='#AAD94C' # Ayu string color
+mint='#95E6CB' # Ayu regexp color
+coral='#F07178' # Ayu markup color
+orange_red='#FF8F40' # Ayu keyword color
+purple='#D2A6FF' # Ayu constant color
+red='#D95757' # Ayu error color
+
+i3lock \
+ --insidever-color=$selection$alpha \
+ --insidewrong-color=$selection$alpha \
+ --inside-color=$background$alpha \
+ --ringver-color=$green$alpha \
+ --ringwrong-color=$red$alpha \
+ --ring-color=$orange$alpha \
+ --line-uses-ring \
+ --keyhl-color=$purple$alpha \
+ --bshl-color=$orange_red$alpha \
+ --separator-color=$selection$alpha \
+ --verif-color=$green \
+ --wrong-color=$red \
+ --modif-color=$red \
+ --layout-color=$bright_blue \
+ --date-color=$bright_blue \
+ --time-color=$orange \
+ --screen 1 \
+ --blur 1 \
+ --clock \
+ --indicator \
+ --time-str="%H:%M:%S" \
+ --date-str="%A %e %B %Y" \
+ --verif-text="Checking..." \
+ --wrong-text="Wrong pswd" \
+ --noinput="No Input" \
+ --lock-text="Locking..." \
+ --lockfailed="Lock Failed" \
+ --radius=120 \
+ --ring-width=10 \
+ --pass-media-keys \
+ --pass-screen-keys \
+ --pass-volume-keys \
+ --date-font="BlexMono Nerd Font Mono" \
+ --verif-font="BlexMono Nerd Font Mono" \
+ --layout-font="BlexMono Nerd Font Mono" \
+ --time-font="BlexMono Nerd Font Mono" \
+ --wrong-font="BlexMono Nerd Font Mono"
diff --git a/lorem b/lorem
new file mode 100755
index 0000000..23ea9a5
--- /dev/null
+++ b/lorem
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+# Check if argument is provided
+if [ $# -eq 0 ]; then
+ echo "Usage: $0 "
+ exit 1
+fi
+
+# Check if argument is a number
+if ! [[ "$1" =~ ^[0-9]+$ ]]; then
+ echo "Error: Please provide a valid number"
+ exit 1
+fi
+
+# Lorem ipsum word bank
+words=(
+ "lorem" "ipsum" "dolor" "sit" "amet" "consectetur" "adipiscing" "elit"
+ "sed" "do" "eiusmod" "tempor" "incididunt" "ut" "labore" "et" "dolore"
+ "magna" "aliqua" "enim" "ad" "minim" "veniam" "quis" "nostrud"
+ "exercitation" "ullamco" "laboris" "nisi" "aliquip" "ex" "ea" "commodo"
+ "consequat" "duis" "aute" "irure" "in" "reprehenderit" "voluptate"
+ "velit" "esse" "cillum" "fugiat" "nulla" "pariatur" "excepteur" "sint"
+ "occaecat" "cupidatat" "non" "proident" "sunt" "culpa" "qui" "officia"
+ "deserunt" "mollit" "anim" "id" "est" "laborum"
+)
+
+# Generate requested number of words
+result=""
+for ((i=1; i<=$1; i++)); do
+ # Get random word from array
+ word=${words[$RANDOM % ${#words[@]}]}
+
+ if [ $i -eq 1 ]; then
+ result="$word"
+ else
+ result="$result $word"
+ fi
+done
+
+echo "$result"
diff --git a/rentry b/rentry
new file mode 100755
index 0000000..1b2ea15
--- /dev/null
+++ b/rentry
@@ -0,0 +1,160 @@
+#!/usr/bin/env python3
+
+import getopt
+import http.cookiejar
+import sys
+import urllib.parse
+import urllib.request
+from http.cookies import SimpleCookie
+from json import loads as json_loads
+from os import environ
+
+_headers = {"Referer": 'https://rentry.co'}
+
+
+class UrllibClient:
+ """Simple HTTP Session Client, keeps cookies."""
+
+ def __init__(self):
+ self.cookie_jar = http.cookiejar.CookieJar()
+ self.opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(self.cookie_jar))
+ urllib.request.install_opener(self.opener)
+
+ def get(self, url, headers={}):
+ request = urllib.request.Request(url, headers=headers)
+ return self._request(request)
+
+ def post(self, url, data=None, headers={}):
+ postdata = urllib.parse.urlencode(data).encode()
+ request = urllib.request.Request(url, postdata, headers)
+ return self._request(request)
+
+ def _request(self, request):
+ response = self.opener.open(request)
+ response.status_code = response.getcode()
+ response.data = response.read().decode('utf-8')
+ return response
+
+
+def raw(url):
+ client = UrllibClient()
+ return json_loads(client.get('https://rentry.co/api/raw/{}'.format(url)).data)
+
+
+def new(url, edit_code, text):
+ client, cookie = UrllibClient(), SimpleCookie()
+
+ cookie.load(vars(client.get('https://rentry.co'))['headers']['Set-Cookie'])
+ csrftoken = cookie['csrftoken'].value
+
+ payload = {
+ 'csrfmiddlewaretoken': csrftoken,
+ 'url': url,
+ 'edit_code': edit_code,
+ 'text': text
+ }
+
+ return json_loads(client.post('https://rentry.co/api/new', payload, headers=_headers).data)
+
+
+def edit(url, edit_code, text):
+ client, cookie = UrllibClient(), SimpleCookie()
+
+ cookie.load(vars(client.get('https://rentry.co'))['headers']['Set-Cookie'])
+ csrftoken = cookie['csrftoken'].value
+
+ payload = {
+ 'csrfmiddlewaretoken': csrftoken,
+ 'edit_code': edit_code,
+ 'text': text
+ }
+
+ return json_loads(client.post('https://rentry.co/api/edit/{}'.format(url), payload, headers=_headers).data)
+
+
+def usage():
+ print('''
+Usage: rentry {new | edit | raw} {-h | --help} {-u | --url} {-p | --edit-code} text
+
+Commands:
+ new create a new entry
+ edit edit an existing entry
+ raw get raw markdown text of an existing entry
+
+Options:
+ -h, --help show this help message and exit
+ -u, --url URL url for the entry, random if not specified
+ -p, --edit-code EDIT-CODE edit code for the entry, random if not specified
+
+Examples:
+ rentry new 'markdown text' # new entry with random url and edit code
+ rentry new -p pw -u example 'text' # with custom edit code and url
+ rentry edit -p pw -u example 'text' # edit the example entry
+ cat file | rentry new # read from pipe and paste it to rentry
+ rentry raw -u example # get raw markdown text
+ rentry raw -u https://rentry.co/example # -u accepts absolute and relative urls
+ ''')
+
+
+if __name__ == '__main__':
+ try:
+ environ.pop('POSIXLY_CORRECT', None)
+ opts, args = getopt.gnu_getopt(sys.argv[1:], "hu:p:", ["help", "url=", "edit-code="])
+ except getopt.GetoptError as e:
+ sys.exit("error: {}".format(e))
+
+ command, url, edit_code, text = None, '', '', None
+
+ for o, a in opts:
+ if o in ("-h", "--help"):
+ usage()
+ sys.exit()
+ elif o in ("-u", "--url"):
+ url = urllib.parse.urlparse(a).path.strip('/')
+ elif o in ("-p", "--edit-code"):
+ edit_code = a
+
+ command = (args[0:1] or [None])[0]
+ command or sys.exit(usage())
+ command in ['new', 'edit', 'raw'] or sys.exit('error: command must be new, edit or raw')
+
+ text = (args[1:2] or [None])[0]
+ if not text and command != 'raw':
+ text = sys.stdin.read().strip()
+ text or sys.exit('error: text is required')
+
+ if command == 'new':
+ response = new(url, edit_code, text)
+ if response['status'] != '200':
+ print('error: {}'.format(response['content']))
+ try:
+ for i in response['errors'].split('.'):
+ i and print(i)
+ sys.exit(1)
+ except:
+ sys.exit(1)
+ else:
+ print('Url: {}\nEdit code: {}'.format(response['url'], response['edit_code']))
+
+ elif command == 'edit':
+ url or sys.exit('error: url is required')
+ edit_code or sys.exit('error: edit code is required')
+
+ response = edit(url, edit_code, text)
+ if response['status'] != '200':
+ print('error: {}'.format(response['content']))
+ try:
+ for i in response['errors'].split('.'):
+ i and print(i)
+ sys.exit(1)
+ except:
+ sys.exit(1)
+ else:
+ print('Ok')
+
+ elif command == 'raw':
+ url or sys.exit('error: url is required')
+ response = raw(url)
+ if response['status'] != '200':
+ sys.exit('error: {}'.format(response['content']))
+ print(response['content'])
diff --git a/waybar/config.jsonc b/waybar/config.jsonc
index 381404a..22e3b66 100644
--- a/waybar/config.jsonc
+++ b/waybar/config.jsonc
@@ -78,7 +78,7 @@
},
"custom/power": {
"format": "",
- "on-click": "zenity --question --text='Are you sure you want to power off?' --icon-name='system-shutdown' --title='Power Off System' && sleep 1 && systemctl poweroff",
+ "on-click": "zenity --question --text='Are you sure you want to power off?' --icon-name='system-shutdown' --title='Power Off System' && sleep 1 && loginctl poweroff",
"tooltip": true,
"tooltip-format": "Power Off"
},
@@ -188,9 +188,9 @@
},
"clock": {
"interval": 1,
- "format": " {:%a:%H:%M}",
+ "format": " {:%a %H:%M}",
"tooltip": true,
- "tooltip-format": "{:L%Y-%m-%d, %A}"
+ "tooltip-format": "{:L%A, %d-%m-%Y}"
},
"tray": {
"icon-size": 14,
diff --git a/waylock b/waylock
new file mode 100755
index 0000000..2d7bb4a
--- /dev/null
+++ b/waylock
@@ -0,0 +1,47 @@
+#!/bin/bash
+
+# Gruvbox Dark Theme Swaylock Command
+# Colors based on the Gruvbox color scheme
+# Background: dark0_hard (#1d2021)
+# Foreground: light1 (#ebdbb2)
+# Red: bright_red (#fb4934)
+# Green: bright_green (#b8bb26)
+# Yellow: bright_yellow (#fabd2f)
+# Blue: bright_blue (#83a598)
+# Purple: bright_purple (#d3869b)
+# Orange: bright_orange (#fe8019)
+
+swaylock \
+ --color 1d2021 \
+ --inside-color 282828 \
+ --inside-clear-color 458588 \
+ --inside-caps-lock-color fabd2f \
+ --inside-ver-color d3869b \
+ --inside-wrong-color fb4934 \
+ --ring-color 3c3836 \
+ --ring-clear-color 689d6a \
+ --ring-caps-lock-color fe8019 \
+ --ring-ver-color b16286 \
+ --ring-wrong-color cc241d \
+ --line-color 00000000 \
+ --line-clear-color 00000000 \
+ --line-caps-lock-color 00000000 \
+ --line-ver-color 00000000 \
+ --line-wrong-color 00000000 \
+ --text-color ebdbb2 \
+ --text-clear-color 1d2021 \
+ --text-caps-lock-color 1d2021 \
+ --text-ver-color 1d2021 \
+ --text-wrong-color 1d2021 \
+ --key-hl-color b8bb26 \
+ --bs-hl-color fb4934 \
+ --caps-lock-key-hl-color fe8019 \
+ --caps-lock-bs-hl-color fb4934 \
+ --separator-color 00000000 \
+ --indicator-radius 100 \
+ --indicator-thickness 7 \
+ --indicator-idle-visible \
+ --font "BlexMono Nerd Font Mono" \
+ --font-size 24 \
+ --show-failed-attempts \
+ --show-keyboard-layout