Compare commits
9 Commits
5dab98c7b9
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 97e6fdca0e | |||
| af151a41af | |||
| 9fcef4b4ed | |||
| e405894cc2 | |||
| e4296a3251 | |||
| db810daf00 | |||
| bd0b49abce | |||
| 0dabe39be9 | |||
| c70ad02033 |
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
cs2_benchmarks/
|
||||||
|
mobos/
|
||||||
6
docs/swap.md
Normal file
6
docs/swap.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
In case of zram swap:
|
||||||
|
|
||||||
|
Make changes persistent by adding to /etc/sysctl.conf or a new file in /etc/sysctl.d/:
|
||||||
|
|
||||||
|
vm.swappiness=100
|
||||||
|
vm.admin_reserve_kbytes=32768
|
||||||
@@ -63,42 +63,59 @@ set $menu fuzzel
|
|||||||
# File manager (Arch alternatives)
|
# File manager (Arch alternatives)
|
||||||
set $filemanager thunar
|
set $filemanager thunar
|
||||||
|
|
||||||
|
# Defaults (kept here so the config still loads even if the included file is missing)
|
||||||
|
set $dp1_mode 3840x2160@165Hz
|
||||||
|
set $dp1_bar_height 40
|
||||||
|
set $dp1_bar_font pango: FontAwesome, monospace 14
|
||||||
|
|
||||||
|
set $dp2_x 3840
|
||||||
|
set $dp2_bar_height 24
|
||||||
|
set $dp2_bar_font pango: FontAwesome, monospace 10
|
||||||
|
|
||||||
|
# Display/bar profile overrides for 330Hz gamemode
|
||||||
|
include /home/raga/.config/sway/scripts/display-profile/display-profile.conf
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Output configuration
|
# Output configuration
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
# Default wallpaper (more resolutions are available in /usr/share/backgrounds/sway/)
|
# Default wallpaper (more resolutions are available in /usr/share/backgrounds/sway/)
|
||||||
# output * bg /usr/share/backgrounds/sway/Sway_Wallpaper_Blue_1920x1080.png fill
|
# output * bg /usr/share/backgrounds/sway/Sway_Wallpaper_Blue_1920x1080.png fill
|
||||||
output * bg /home/raga/.config/sway/wallpaper.jpg fill
|
# output * bg /home/raga/.config/sway/wallpaper.jpg fill
|
||||||
|
|
||||||
# Multi-monitor setup
|
# Multi-monitor setup
|
||||||
# You can get your output names by running: swaymsg -t get_outputs
|
# You can get your output names by running: swaymsg -t get_outputs
|
||||||
# DP-2 is the primary monitor on the left, and DP-1 is on the right.
|
# DP-2 is the primary monitor on the left, and DP-1 is on the right.
|
||||||
output HDMI-A-1 {
|
output DP-1 {
|
||||||
#output DP-2 {
|
adaptive_sync on
|
||||||
# mode 2560x1440@60Hz
|
render_bit_depth 10
|
||||||
mode 2560x1440@120Hz
|
|
||||||
position 0 0
|
position 0 0
|
||||||
|
|
||||||
|
# ECO
|
||||||
|
# mode 2560x1440@60Hz
|
||||||
|
|
||||||
|
# FULL
|
||||||
|
mode $dp1_mode
|
||||||
}
|
}
|
||||||
|
|
||||||
output DP-1 {
|
output DP-2 {
|
||||||
modeline 586.59 2560 2568 2600 2640 1440 1529 1537 1543 +hsync -vsync
|
position $dp2_x 0
|
||||||
position 2560 0
|
|
||||||
|
# ECO
|
||||||
|
# mode 2560x1440@60Hz
|
||||||
|
|
||||||
|
# FULL
|
||||||
|
# modeline 586.59 2560 2568 2600 2640 1440 1529 1537 1543 +hsync -vsync
|
||||||
}
|
}
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Idle configuration
|
# Idle configuration
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
# Lock screen after 900 seconds of inactivity, then turn off displays
|
|
||||||
#exec swayidle -w \
|
|
||||||
# timeout 900 'swaylock -f -c 000000' \
|
|
||||||
# timeout 1800 'swaymsg "output * power off"' resume 'swaymsg "output * power on"' \
|
|
||||||
# before-sleep 'swaylock -f -c 000000'
|
|
||||||
|
|
||||||
# Lock screen after 900 seconds of inactivity
|
|
||||||
exec swayidle -w \
|
exec swayidle -w \
|
||||||
timeout 900 'swaylock -f -c 000000' \
|
timeout 900 'swaylock -f -c 000000' \
|
||||||
|
# timeout 1800 'swaymsg "output * power off"' resume 'swaymsg "output * power on"' \
|
||||||
before-sleep 'swaylock -f -c 000000'
|
before-sleep 'swaylock -f -c 000000'
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
@@ -106,9 +123,13 @@ exec swayidle -w \
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
# Estonian keyboard layout configuration
|
# Estonian keyboard layout configuration
|
||||||
input type:keyboard {
|
# input type:keyboard {
|
||||||
xkb_layout "ee"
|
# xkb_layout "ee"
|
||||||
xkb_variant "nodeadkeys"
|
# xkb_variant "nodeadkeys"
|
||||||
|
# }
|
||||||
|
input * {
|
||||||
|
xkb_layout "ee,it"
|
||||||
|
# xkb_options "grp:alt_shift_toggle"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Enable touchpad tap, natural scroll
|
# Enable touchpad tap, natural scroll
|
||||||
@@ -131,6 +152,7 @@ input type:pointer {
|
|||||||
# Floating window rules
|
# Floating window rules
|
||||||
floating_maximum_size -1 x -1
|
floating_maximum_size -1 x -1
|
||||||
for_window [app_id="floating_window"] floating enable
|
for_window [app_id="floating_window"] floating enable
|
||||||
|
for_window [app_id="pavucontrol"] floating enable
|
||||||
|
|
||||||
# Border configuration
|
# Border configuration
|
||||||
default_floating_border pixel 1
|
default_floating_border pixel 1
|
||||||
@@ -159,6 +181,9 @@ floating_modifier $mod normal
|
|||||||
# Launcher dialogs
|
# Launcher dialogs
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
|
## Keyboard // Toggle Layout // <Alt><Shift> l ##
|
||||||
|
bindsym $alt+Shift+L input * xkb_switch_layout next
|
||||||
|
|
||||||
## Launch // Terminal // <> Enter ##
|
## Launch // Terminal // <> Enter ##
|
||||||
bindsym $mod+Return exec $term
|
bindsym $mod+Return exec $term
|
||||||
|
|
||||||
@@ -194,32 +219,47 @@ bindsym $mod+Ctrl+r reload
|
|||||||
bindsym $mod+Shift+e exec swaynag -t warning -m 'Do you really want to exit sway? This will end your Wayland session.' -B 'Yes, exit sway' 'swaymsg exit'
|
bindsym $mod+Shift+e exec swaynag -t warning -m 'Do you really want to exit sway? This will end your Wayland session.' -B 'Yes, exit sway' 'swaymsg exit'
|
||||||
|
|
||||||
## Session // Reboot // <><Shift> b ##
|
## Session // Reboot // <><Shift> b ##
|
||||||
bindsym $mod+Shift+b exec systemctl reboot
|
#bindsym $mod+Shift+b exec systemctl reboot
|
||||||
|
|
||||||
## Session // Power Down // <><Shift> p ##
|
## Session // Power Down // <><Shift> p ##
|
||||||
bindsym $mod+Shift+p exec systemctl poweroff
|
#bindsym $mod+Shift+p exec systemctl poweroff
|
||||||
|
|
||||||
## Session // Lock Screen // <> Escape ##
|
## Session // Lock Screen // <> Escape ##
|
||||||
bindsym $mod+Escape exec swaylock -f -c 000000
|
bindsym $mod+Escape exec swaylock -f -c 000000
|
||||||
|
|
||||||
## Session // Sleep // <><Shift> s ##
|
## Session // Sleep // <><Shift> s ##
|
||||||
bindsym $mod+Shift+s exec systemctl suspend
|
#bindsym $mod+Shift+s exec systemctl suspend
|
||||||
|
|
||||||
## Mouse // Toggle Position // <> q ##
|
###############################################################################
|
||||||
#bindsym q exec /home/raga/repos/linux/sway-new-config/mouse-toggle.sh
|
# Custom scripts (OSRS mode)
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
## Mouse // Enable/Disable Toggle // <><Shift> o ##
|
set $osrs_scripts /home/raga/repos/linux/sway-new-config/scripts/osrs
|
||||||
bindsym $mod+Shift+o exec /home/raga/repos/linux/sway-new-config/mouse-toggle.sh toggle
|
set $osrs_mode OSRS
|
||||||
|
|
||||||
|
#bindsym f12 mode "$osrs_mode"
|
||||||
|
mode "$osrs_mode" {
|
||||||
|
bindsym q exec $osrs_scripts/osrs-drop.sh
|
||||||
|
bindsym w exec $osrs_scripts/osrs-click.sh
|
||||||
|
bindsym o exec $osrs_scripts/mouse-toggle.sh toggle
|
||||||
|
bindsym a exec kitty -e $osrs_scripts/autoclicker.sh
|
||||||
|
#bindsym Escape exec $osrs_scripts/autoclicker-stop.sh
|
||||||
|
|
||||||
|
## Resize // Exit OSRS Mode // Escape or Enter ##
|
||||||
|
bindsym Return mode "default"
|
||||||
|
bindsym Escape mode "default"
|
||||||
|
bindsym f12 mode "default"
|
||||||
|
}
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# System Management (Arch Linux alternatives)
|
# System Management (Arch Linux alternatives)
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
## Modify // Settings // <> c ##
|
## Modify // Settings // <> c ##
|
||||||
bindsym $mod+c exec env XDG_CURRENT_DESKTOP=GNOME gnome-control-center
|
#bindsym $mod+c exec env XDG_CURRENT_DESKTOP=GNOME gnome-control-center
|
||||||
|
|
||||||
## Modify // Display Settings // <> d ##
|
## Modify // Display Settings // <> d ##
|
||||||
bindsym $mod+d exec wdisplays
|
#bindsym $mod+d exec wdisplays
|
||||||
|
|
||||||
## Modify // Wifi Settings // <> w ##
|
## Modify // Wifi Settings // <> w ##
|
||||||
bindsym $mod+w exec nm-connection-editor
|
bindsym $mod+w exec nm-connection-editor
|
||||||
@@ -300,7 +340,7 @@ bindsym $mod+Ctrl+Shift+Tab workspace prev_on_output
|
|||||||
bindsym $mod+Ctrl+h workspace prev_on_output
|
bindsym $mod+Ctrl+h workspace prev_on_output
|
||||||
|
|
||||||
## Navigate // Scratchpad // <><Ctrl> a ##
|
## Navigate // Scratchpad // <><Ctrl> a ##
|
||||||
bindsym $mod+Ctrl+a scratchpad show
|
#bindsym $mod+Ctrl+a scratchpad show
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Window and Workspace Configuration
|
# Window and Workspace Configuration
|
||||||
@@ -331,10 +371,10 @@ bindsym $mod+Ctrl+Shift+k move workspace to output up
|
|||||||
bindsym $mod+Ctrl+Shift+l move workspace to output right
|
bindsym $mod+Ctrl+Shift+l move workspace to output right
|
||||||
|
|
||||||
## Modify // Vertical Window Orientation // <> v ##
|
## Modify // Vertical Window Orientation // <> v ##
|
||||||
bindsym $mod+v splitv
|
#bindsym $mod+v splitv
|
||||||
|
|
||||||
## Modify // Horizontal Window Orientation // <> g ##
|
## Modify // Horizontal Window Orientation // <> g ##
|
||||||
bindsym $mod+g splith
|
#bindsym $mod+g splith
|
||||||
|
|
||||||
## Modify // Toggle Window Orientation // <> BackSpace ##
|
## Modify // Toggle Window Orientation // <> BackSpace ##
|
||||||
bindsym $mod+BackSpace split toggle
|
bindsym $mod+BackSpace split toggle
|
||||||
@@ -346,13 +386,13 @@ bindsym $mod+f fullscreen toggle
|
|||||||
bindsym $mod+Shift+f floating toggle
|
bindsym $mod+Shift+f floating toggle
|
||||||
|
|
||||||
## Modify // Move to Scratchpad // <><Ctrl> m ##
|
## Modify // Move to Scratchpad // <><Ctrl> m ##
|
||||||
bindsym $mod+Ctrl+m move to scratchpad
|
#bindsym $mod+Ctrl+m move to scratchpad
|
||||||
|
|
||||||
## Modify // Tile/Float Focus Toggle // <><Shift> t ##
|
## Modify // Tile/Float Focus Toggle // <><Shift> t ##
|
||||||
bindsym $mod+Shift+t focus mode_toggle
|
#bindsym $mod+Shift+t focus mode_toggle
|
||||||
|
|
||||||
## Modify // Window Layout Mode // <> t ##
|
## Modify // Window Layout Mode // <> t ##
|
||||||
bindsym $mod+t layout toggle tabbed splith splitv
|
#bindsym $mod+t layout toggle tabbed splith splitv
|
||||||
|
|
||||||
# Move focused container to workspace
|
# Move focused container to workspace
|
||||||
## Modify // Move Window to Workspace 1 - 10 // <><Shift> 0..9 ##
|
## Modify // Move Window to Workspace 1 - 10 // <><Shift> 0..9 ##
|
||||||
@@ -403,14 +443,14 @@ bindsym $mod+$alt+$ws_high_key+$ws8_key move container to workspace number $ws18
|
|||||||
bindsym $mod+$alt+$ws_high_key+$ws9_key move container to workspace number $ws19; workspace number $ws19
|
bindsym $mod+$alt+$ws_high_key+$ws9_key move container to workspace number $ws19; workspace number $ws19
|
||||||
|
|
||||||
# Layout bindings (matching i3 defaults)
|
# Layout bindings (matching i3 defaults)
|
||||||
bindsym $mod+s layout stacking
|
#bindsym $mod+s layout stacking
|
||||||
bindsym $mod+e layout toggle split
|
#bindsym $mod+e layout toggle split
|
||||||
|
|
||||||
# Move the currently focused window to the scratchpad
|
# Move the currently focused window to the scratchpad
|
||||||
bindsym $mod+Shift+minus move scratchpad
|
#bindsym $mod+Shift+minus move scratchpad
|
||||||
|
|
||||||
# Show the next scratchpad window or hide the focused scratchpad window.
|
# Show the next scratchpad window or hide the focused scratchpad window.
|
||||||
bindsym $mod+minus scratchpad show
|
#bindsym $mod+minus scratchpad show
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Resize Mode
|
# Resize Mode
|
||||||
@@ -426,10 +466,10 @@ mode "Resize Mode" {
|
|||||||
bindsym Up resize shrink height 6 px or 6 ppt
|
bindsym Up resize shrink height 6 px or 6 ppt
|
||||||
bindsym Right resize grow width 6 px or 6 ppt
|
bindsym Right resize grow width 6 px or 6 ppt
|
||||||
|
|
||||||
bindsym Shift+Left resize shrink width 24 px or 24 ppt
|
bindsym Shift+Left resize shrink width 48 px or 48 ppt
|
||||||
bindsym Shift+Down resize grow height 24 px or 24 ppt
|
bindsym Shift+Down resize grow height 48 px or 48 ppt
|
||||||
bindsym Shift+Up resize shrink height 24 px or 24 ppt
|
bindsym Shift+Up resize shrink height 48 px or 48 ppt
|
||||||
bindsym Shift+Right resize grow width 24 px or 24 ppt
|
bindsym Shift+Right resize grow width 48 px or 48 ppt
|
||||||
|
|
||||||
## Resize // Resize Window // k j h l ##
|
## Resize // Resize Window // k j h l ##
|
||||||
bindsym $left resize shrink width 6 px or 6 ppt
|
bindsym $left resize shrink width 6 px or 6 ppt
|
||||||
@@ -437,10 +477,10 @@ mode "Resize Mode" {
|
|||||||
bindsym $up resize shrink height 6 px or 6 ppt
|
bindsym $up resize shrink height 6 px or 6 ppt
|
||||||
bindsym $right resize grow width 6 px or 6 ppt
|
bindsym $right resize grow width 6 px or 6 ppt
|
||||||
|
|
||||||
bindsym Shift+$left resize shrink width 24 px or 24 ppt
|
bindsym Shift+$left resize shrink width 48 px or 48 ppt
|
||||||
bindsym Shift+$down resize grow height 24 px or 24 ppt
|
bindsym Shift+$down resize grow height 48 px or 48 ppt
|
||||||
bindsym Shift+$up resize shrink height 24 px or 24 ppt
|
bindsym Shift+$up resize shrink height 48 px or 48 ppt
|
||||||
bindsym Shift+$right resize grow width 24 px or 24 ppt
|
bindsym Shift+$right resize grow width 48 px or 48 ppt
|
||||||
|
|
||||||
## Resize // Exit Resize Mode // Escape or Enter ##
|
## Resize // Exit Resize Mode // Escape or Enter ##
|
||||||
bindsym Return mode "default"
|
bindsym Return mode "default"
|
||||||
@@ -454,9 +494,9 @@ bindsym $mod+r mode "Resize Mode"
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
# Volume control (works with both PulseAudio and PipeWire)
|
# Volume control (works with both PulseAudio and PipeWire)
|
||||||
bindsym --locked XF86AudioMute exec pactl set-sink-mute @DEFAULT_SINK@ toggle && ~/.config/sway/volume-notify-sway.sh
|
bindsym --locked XF86AudioMute exec pactl set-sink-mute @DEFAULT_SINK@ toggle && ~/.config/sway/scripts/sway/volume-notify.sh
|
||||||
bindsym --locked XF86AudioLowerVolume exec pactl set-sink-volume @DEFAULT_SINK@ -5% && ~/.config/sway/volume-notify-sway.sh
|
bindsym --locked XF86AudioLowerVolume exec pactl set-sink-volume @DEFAULT_SINK@ -5% && ~/.config/sway/scripts/sway/volume-notify.sh
|
||||||
bindsym --locked XF86AudioRaiseVolume exec pactl set-sink-volume @DEFAULT_SINK@ +5% && ~/.config/sway/volume-notify-sway.sh
|
bindsym --locked XF86AudioRaiseVolume exec pactl set-sink-volume @DEFAULT_SINK@ +5% && ~/.config/sway/scripts/sway/volume-notify.sh
|
||||||
bindsym --locked XF86AudioMicMute exec pactl set-source-mute @DEFAULT_SOURCE@ toggle
|
bindsym --locked XF86AudioMicMute exec pactl set-source-mute @DEFAULT_SOURCE@ toggle
|
||||||
|
|
||||||
# Brightness control
|
# Brightness control
|
||||||
@@ -465,6 +505,7 @@ bindsym --locked XF86MonBrightnessUp exec brightnessctl set 5%+
|
|||||||
|
|
||||||
# Screenshots
|
# Screenshots
|
||||||
bindsym Print exec grim - | swappy -f -
|
bindsym Print exec grim - | swappy -f -
|
||||||
|
|
||||||
bindsym $mod+Print exec grim -g "$(slurp)" - | swappy -f -
|
bindsym $mod+Print exec grim -g "$(slurp)" - | swappy -f -
|
||||||
|
|
||||||
## Modify // Toggle Bar // <> i ##
|
## Modify // Toggle Bar // <> i ##
|
||||||
@@ -475,15 +516,40 @@ bindsym $mod+i bar mode toggle
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
bar {
|
bar {
|
||||||
|
output DP-1
|
||||||
position bottom
|
position bottom
|
||||||
mode dock
|
mode dock
|
||||||
#font pango:monospace 10
|
height $dp1_bar_height
|
||||||
font pango: FontAwesome, monospace 10
|
font $dp1_bar_font
|
||||||
|
separator_symbol " "
|
||||||
|
strip_workspace_numbers yes
|
||||||
|
workspace_min_width 36
|
||||||
|
|
||||||
|
status_command i3status-rs ~/.config/sway/i3status-rust.toml || while date +'%Y-%m-%d %l:%M:%S %p'; do sleep 1; done
|
||||||
|
|
||||||
|
colors {
|
||||||
|
background #000000
|
||||||
|
statusline #ffffff
|
||||||
|
separator #666666
|
||||||
|
|
||||||
|
# border backgr. text
|
||||||
|
focused_workspace #000000 #ffffff #000000
|
||||||
|
active_workspace #ffffff #000000 #ffffff
|
||||||
|
inactive_workspace #000000 #000000 #ffffff
|
||||||
|
urgent_workspace #000000 #ff0000 #ffffff
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bar {
|
||||||
|
output DP-2
|
||||||
|
position bottom
|
||||||
|
mode dock
|
||||||
|
height $dp2_bar_height
|
||||||
|
font $dp2_bar_font
|
||||||
separator_symbol " "
|
separator_symbol " "
|
||||||
strip_workspace_numbers yes
|
strip_workspace_numbers yes
|
||||||
workspace_min_width 36
|
workspace_min_width 36
|
||||||
|
|
||||||
# Try to use i3status-rust for better functionality, fallback to basic status
|
|
||||||
status_command i3status-rs ~/.config/sway/i3status-rust.toml || while date +'%Y-%m-%d %l:%M:%S %p'; do sleep 1; done
|
status_command i3status-rs ~/.config/sway/i3status-rust.toml || while date +'%Y-%m-%d %l:%M:%S %p'; do sleep 1; done
|
||||||
|
|
||||||
colors {
|
colors {
|
||||||
@@ -514,6 +580,7 @@ exec lxqt-policykit-agent # Authentication agent (comment out if not needed)
|
|||||||
|
|
||||||
exec --no-startup-id blueman-applet
|
exec --no-startup-id blueman-applet
|
||||||
exec --no-startup-id nm-applet
|
exec --no-startup-id nm-applet
|
||||||
|
exec --no-startup-id home_dotfiles/.config/sway/scripts/i3status/set-random-bg.sh
|
||||||
|
|
||||||
# Include additional config files if they exist
|
# Include additional config files if they exist
|
||||||
include /etc/sway/config.d/*
|
include /etc/sway/config.d/*
|
||||||
|
|||||||
@@ -1,9 +1,42 @@
|
|||||||
# Advanced i3status-rust configuration
|
# Advanced i3status-rust configuration
|
||||||
# Based on the i3xrocks blocks from your i3 setup
|
# Based on the i3xrocks blocks from your i3 setup
|
||||||
|
|
||||||
|
[[block]]
|
||||||
|
block = "custom"
|
||||||
|
command = "~/.config/sway/scripts/osrs/osrs-mode-status.sh"
|
||||||
|
format = " $text "
|
||||||
|
interval = 1
|
||||||
|
click = [
|
||||||
|
{button = "left", cmd = "~/.config/sway/scripts/osrs/osrs-mode-toggle.sh", update = true}
|
||||||
|
]
|
||||||
|
|
||||||
|
[[block]]
|
||||||
|
block = "custom"
|
||||||
|
command = "~/.config/sway/scripts/display-profile/display-profile-status.sh"
|
||||||
|
format = " $text "
|
||||||
|
interval = 1
|
||||||
|
click = [
|
||||||
|
{button = "left", cmd = "~/.config/sway/scripts/display-profile/display-profile-toggle.sh", update = true}
|
||||||
|
]
|
||||||
|
|
||||||
|
[[block]]
|
||||||
|
block = "custom"
|
||||||
|
command = "echo ''"
|
||||||
|
format = " $text "
|
||||||
|
interval = 1
|
||||||
|
click = [
|
||||||
|
{button = "left", cmd = "~/.config/sway/scripts/i3status/set-random-bg.sh", update = false},
|
||||||
|
]
|
||||||
|
|
||||||
|
#[[block]]
|
||||||
|
#block = "custom"
|
||||||
|
#command = "~/.config/sway/scripts/i3status/get-focused-window.sh"
|
||||||
|
#format = " $text "
|
||||||
|
#interval = 5
|
||||||
|
|
||||||
[[block]]
|
[[block]]
|
||||||
block = "net"
|
block = "net"
|
||||||
format = " $icon {$signal_strength $ssid $frequency|Wired connection} via $device "
|
format = " $icon {$signal_strength $ssid $frequency|Wired} @ $device "
|
||||||
interval = 1
|
interval = 1
|
||||||
|
|
||||||
[[block]]
|
[[block]]
|
||||||
@@ -43,7 +76,7 @@ disconnected_format = ""
|
|||||||
# Custom Bluetooth connected devices block
|
# Custom Bluetooth connected devices block
|
||||||
[[block]]
|
[[block]]
|
||||||
block = "custom"
|
block = "custom"
|
||||||
command = "~/.config/sway/bluetooth-sway.sh"
|
command = "~/.config/sway/scripts/i3status/bluetooth.sh"
|
||||||
format = " $text "
|
format = " $text "
|
||||||
interval = 10
|
interval = 10
|
||||||
click = [
|
click = [
|
||||||
@@ -54,7 +87,7 @@ click = [
|
|||||||
# Custom weather block using your wttr.in script
|
# Custom weather block using your wttr.in script
|
||||||
# [[block]]
|
# [[block]]
|
||||||
# block = "custom"
|
# block = "custom"
|
||||||
# command = "~/.config/sway/weather-sway.sh"
|
# command = "~/.config/sway/scripts/i3status/wttrin-weather.sh"
|
||||||
# format = " 🌤 $text "
|
# format = " 🌤 $text "
|
||||||
# interval = 1800
|
# interval = 1800
|
||||||
# click = [
|
# click = [
|
||||||
@@ -66,7 +99,7 @@ click = [
|
|||||||
# Uncomment and modify this block if you want weather for a different city
|
# Uncomment and modify this block if you want weather for a different city
|
||||||
[[block]]
|
[[block]]
|
||||||
block = "custom"
|
block = "custom"
|
||||||
command = "~/.config/sway/weather-sway.sh"
|
command = "~/.config/sway/scripts/i3status/wttrin-weather.sh"
|
||||||
format = "$text"
|
format = "$text"
|
||||||
interval = 1800
|
interval = 1800
|
||||||
|
|
||||||
@@ -75,7 +108,7 @@ interval = 1800
|
|||||||
# 1 = current conditions, 2 = current + today, 3 = current + today + tomorrow, 4 = current + 3 days
|
# 1 = current conditions, 2 = current + today, 3 = current + today + tomorrow, 4 = current + 3 days
|
||||||
# [[block]]
|
# [[block]]
|
||||||
# block = "custom"
|
# block = "custom"
|
||||||
# command = "weather_format='2' ~/.config/sway/weather-sway.sh"
|
# command = "weather_format='2' ~/.config/sway/scripts/i3status/wttrin-weather.sh"
|
||||||
# format = " 📅 $text "
|
# format = " 📅 $text "
|
||||||
# interval = 1800
|
# interval = 1800
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
PROFILE_FILE="/home/raga/.config/sway/scripts/display-profile/display-profile.conf"
|
||||||
|
|
||||||
|
mode_str=""
|
||||||
|
if [[ -f "$PROFILE_FILE" ]]; then
|
||||||
|
mode_str="$(awk '$1=="set" && $2=="$dp1_mode" {print $3; found=1} END {if(!found) print ""}' "$PROFILE_FILE" 2>/dev/null)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Display-related FontAwesome icon + a short label.
|
||||||
|
case "$mode_str" in
|
||||||
|
3840x2160@*|4096x2160@*) echo " 4K";;
|
||||||
|
1920x1080@*) echo " 1080p";;
|
||||||
|
"") echo "";;
|
||||||
|
*) echo " ${mode_str}";;
|
||||||
|
esac
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Toggle DP-1 between 4K@165 and 1080p@330 and keep DP-2 positioned flush so
|
||||||
|
# you don't get a "dead gap" for the mouse.
|
||||||
|
|
||||||
|
PROFILE_FILE="/home/raga/.config/sway/scripts/display-profile/display-profile.conf"
|
||||||
|
|
||||||
|
MODE_4K="3840x2160@165Hz"
|
||||||
|
MODE_GAME="1920x1080@330Hz"
|
||||||
|
|
||||||
|
# Bar tuning per mode
|
||||||
|
BAR_HEIGHT_4K="40"
|
||||||
|
BAR_FONT_4K="pango: FontAwesome, monospace 14"
|
||||||
|
|
||||||
|
BAR_HEIGHT_GAME="16"
|
||||||
|
BAR_FONT_GAME="pango: FontAwesome, monospace 8"
|
||||||
|
|
||||||
|
# DP-2 bar settings (static)
|
||||||
|
DP2_BAR_HEIGHT="24"
|
||||||
|
DP2_BAR_FONT="pango: FontAwesome, monospace 10"
|
||||||
|
|
||||||
|
get_current_profile_mode() {
|
||||||
|
# Reads the last-written profile state instead of querying the monitor.
|
||||||
|
# This makes toggling deterministic even if the display reports odd modes.
|
||||||
|
if [[ ! -f "$PROFILE_FILE" ]]; then
|
||||||
|
echo "$MODE_4K"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Example line: set $dp1_mode 3840x2160@165Hz
|
||||||
|
awk '$1=="set" && $2=="$dp1_mode" {print $3; found=1} END {if(!found) exit 1}' "$PROFILE_FILE" 2>/dev/null \
|
||||||
|
|| echo "$MODE_4K"
|
||||||
|
}
|
||||||
|
|
||||||
|
write_profile() {
|
||||||
|
local dp1_mode="$1"
|
||||||
|
local dp1_bar_height="$2"
|
||||||
|
local dp1_bar_font="$3"
|
||||||
|
local dp2_x="$4"
|
||||||
|
|
||||||
|
local tmp
|
||||||
|
tmp="$(mktemp)"
|
||||||
|
cat >"$tmp" <<EOF
|
||||||
|
# Autogenerated by display-profile-toggle.sh. Manual edits will be overwritten.
|
||||||
|
|
||||||
|
set \$dp1_mode ${dp1_mode}
|
||||||
|
set \$dp1_bar_height ${dp1_bar_height}
|
||||||
|
set \$dp1_bar_font ${dp1_bar_font}
|
||||||
|
|
||||||
|
set \$dp2_x ${dp2_x}
|
||||||
|
set \$dp2_bar_height ${DP2_BAR_HEIGHT}
|
||||||
|
set \$dp2_bar_font ${DP2_BAR_FONT}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
mkdir -p "$(dirname "$PROFILE_FILE")"
|
||||||
|
mv -f "$tmp" "$PROFILE_FILE"
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
local current_mode
|
||||||
|
current_mode="$(get_current_profile_mode)"
|
||||||
|
|
||||||
|
if [[ "$current_mode" == "$MODE_4K" ]]; then
|
||||||
|
# Switch to game mode (1080p @ high refresh)
|
||||||
|
write_profile "$MODE_GAME" "$BAR_HEIGHT_GAME" "$BAR_FONT_GAME" "1920"
|
||||||
|
else
|
||||||
|
# Switch back to 4K
|
||||||
|
write_profile "$MODE_4K" "$BAR_HEIGHT_4K" "$BAR_FONT_4K" "3840"
|
||||||
|
fi
|
||||||
|
|
||||||
|
swaymsg reload >/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
# Default display profile
|
||||||
|
# Rewritten and toggled in `display-profile-toggle.sh`
|
||||||
|
|
||||||
|
# DP-1 (4K / gaming output)
|
||||||
|
set $dp1_mode 3840x2160@165Hz
|
||||||
|
set $dp1_bar_height 40
|
||||||
|
set $dp1_bar_font pango: FontAwesome, monospace 14
|
||||||
|
|
||||||
|
# DP-2 (secondary output)
|
||||||
|
set $dp2_x 3840
|
||||||
|
set $dp2_bar_height 24
|
||||||
|
set $dp2_bar_font pango: FontAwesome, monospace 10
|
||||||
5
home_dotfiles/.config/sway/scripts/i3status/get-focused-window.sh
Executable file
5
home_dotfiles/.config/sway/scripts/i3status/get-focused-window.sh
Executable file
@@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
FOCUSED=$(swaymsg -t get_tree | jq '.. | select(.type?) | select(.focused==true) | .name')
|
||||||
|
|
||||||
|
echo "$FOCUSED"
|
||||||
32
home_dotfiles/.config/sway/scripts/i3status/set-random-bg.sh
Executable file
32
home_dotfiles/.config/sway/scripts/i3status/set-random-bg.sh
Executable file
@@ -0,0 +1,32 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Find a random image file
|
||||||
|
#IMAGE=$(find /run/media/raga/970/qBittorrent/nsfw/xd -type f \( -name '*.png' -o -name '*.jpg' -o -name '*.jpeg' \) | shuf -n 1)
|
||||||
|
IMAGE=$(find /run/media/raga/970/images/cars/wallpaper -type f \( -name '*.png' -o -name '*.jpg' -o -name '*.jpeg' \) | shuf -n 1)
|
||||||
|
|
||||||
|
if [ -n "$IMAGE" ]; then
|
||||||
|
echo "Image: $IMAGE"
|
||||||
|
|
||||||
|
# Try to get image dimensions using identify (ImageMagick)
|
||||||
|
DIMENSIONS=$(identify -format "%wx%h" "$IMAGE" 2>/dev/null)
|
||||||
|
|
||||||
|
if [ -n "$DIMENSIONS" ]; then
|
||||||
|
echo "Dimensions: $DIMENSIONS"
|
||||||
|
WIDTH=$(echo "$DIMENSIONS" | cut -d'x' -f1)
|
||||||
|
HEIGHT=$(echo "$DIMENSIONS" | cut -d'x' -f2)
|
||||||
|
|
||||||
|
# Determine if portrait (height > width) or landscape
|
||||||
|
if [ "$HEIGHT" -gt "$WIDTH" ]; then
|
||||||
|
# Portrait image - use "fit" to maintain aspect ratio
|
||||||
|
echo "Portrait image - using fit"
|
||||||
|
swaymsg "output * bg \"$IMAGE\" fit"
|
||||||
|
else
|
||||||
|
# Landscape image - use "fill" to fill the screen
|
||||||
|
echo "Landscape image - using fill"
|
||||||
|
swaymsg "output * bg \"$IMAGE\" fill"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# Fallback to fill if we can't determine dimensions
|
||||||
|
echo "Could not determine dimensions - using fill"
|
||||||
|
swaymsg "output * bg \"$IMAGE\" fill"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
115
home_dotfiles/.config/sway/scripts/i3status/wttrin-weather.sh
Executable file
115
home_dotfiles/.config/sway/scripts/i3status/wttrin-weather.sh
Executable file
@@ -0,0 +1,115 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -Eeu -o pipefail
|
||||||
|
|
||||||
|
# Improved weather script for i3status-rust using JSON API
|
||||||
|
# Based on the original weather script but optimized for Sway/i3status-rust
|
||||||
|
|
||||||
|
# Location (defaults to Pärnu as in your original script)
|
||||||
|
VALUE_WEATHER_LOCATION=${weather_location:-"Pärnu"}
|
||||||
|
VALUE_WEATHER_ERROR_MESSAGE=${error_message:-"⛔"}
|
||||||
|
|
||||||
|
# Determine units to use for temperature
|
||||||
|
# We don't supply a default here because wttr.in is "smart" enough to choose for us
|
||||||
|
WEATHER_UNIT=${weather_unit:-""}
|
||||||
|
if [ -n "${WEATHER_UNIT}" ]; then
|
||||||
|
WEATHER_UNIT="&${WEATHER_UNIT}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Use JSON API to get all data in a single request
|
||||||
|
VALUE_FETCH_WEATHER_URL="https://wttr.in/${VALUE_WEATHER_LOCATION}?format=j1"
|
||||||
|
|
||||||
|
# Get weather data using JSON API
|
||||||
|
WEATHER_JSON=$(curl -sS "$VALUE_FETCH_WEATHER_URL" 2>/dev/null || echo "{}")
|
||||||
|
|
||||||
|
# Check for errors
|
||||||
|
if echo "$WEATHER_JSON" | grep -q "Unknown location"; then
|
||||||
|
echo "${VALUE_WEATHER_ERROR_MESSAGE}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Extract data using jq (should be available on most systems)
|
||||||
|
if command -v jq &>/dev/null; then
|
||||||
|
# Extract current weather condition and temperature
|
||||||
|
WEATHER_CONDITION=$(echo "$WEATHER_JSON" | jq -r '.current_condition[0].weatherDesc[0].value' 2>/dev/null || echo "")
|
||||||
|
TEMP_C=$(echo "$WEATHER_JSON" | jq -r '.current_condition[0].temp_C' 2>/dev/null || echo "")
|
||||||
|
|
||||||
|
# Extract sunrise and sunset times
|
||||||
|
SUNRISE=$(echo "$WEATHER_JSON" | jq -r '.weather[0].astronomy[0].sunrise' 2>/dev/null || echo "")
|
||||||
|
SUNSET=$(echo "$WEATHER_JSON" | jq -r '.weather[0].astronomy[0].sunset' 2>/dev/null || echo "")
|
||||||
|
|
||||||
|
# Convert to simple format if we have data
|
||||||
|
if [ -n "$WEATHER_CONDITION" ] && [ -n "$TEMP_C" ]; then
|
||||||
|
# Map weather conditions to icons (simplified)
|
||||||
|
case "$WEATHER_CONDITION" in
|
||||||
|
*"Sunny"*|*"Clear"*) ICON="☀️";;
|
||||||
|
*"Partly cloudy"*|*"Cloudy"*) ICON="⛅";;
|
||||||
|
*"Overcast"*) ICON="☁️";;
|
||||||
|
*"Rain"*|*"Drizzle"*) ICON="🌧️";;
|
||||||
|
*"Snow"*) ICON="❄️";;
|
||||||
|
*"Thunder"*) ICON="⛈️";;
|
||||||
|
*"Fog"*|*"Mist"*) ICON="🌫️";;
|
||||||
|
*) ICON="🌤️";;
|
||||||
|
esac
|
||||||
|
|
||||||
|
WEATHER="${ICON} ${TEMP_C}°C"
|
||||||
|
|
||||||
|
# Format sunrise/sunset times (convert from "09:10 AM" to "09:10")
|
||||||
|
if [ -n "$SUNRISE" ] && [ -n "$SUNSET" ]; then
|
||||||
|
# Remove AM/PM and convert to 24-hour format
|
||||||
|
SUNRISE_24=$(echo "$SUNRISE" | sed 's/ AM//;s/ PM//;s/^0//' | awk -F: '{if($1==12) print "00:"$2; else if($1<12) print $1":"$2; else print $1":"$2}')
|
||||||
|
SUNSET_24=$(echo "$SUNSET" | sed 's/ AM//;s/ PM//;s/^0//' | awk -F: '{if($1==12) print "00:"$2; else if($1<12) print $1":"$2; else print $1":"$2}')
|
||||||
|
|
||||||
|
# Remove leading zeros from hours for consistency
|
||||||
|
SUNRISE_24=$(echo "$SUNRISE_24" | sed 's/^0//')
|
||||||
|
SUNSET_24=$(echo "$SUNSET_24" | sed 's/^0//')
|
||||||
|
|
||||||
|
SUNRISE_SUNSET_TEXT=" (${SUNRISE_24}-${SUNSET_24})"
|
||||||
|
else
|
||||||
|
SUNRISE_SUNSET_TEXT=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Output for i3status-rust (plain text)
|
||||||
|
echo "${WEATHER}${SUNRISE_SUNSET_TEXT}"
|
||||||
|
else
|
||||||
|
echo "${VALUE_WEATHER_ERROR_MESSAGE}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# Fallback to original method if jq is not available
|
||||||
|
echo "⚠️ jq not found, using fallback method"
|
||||||
|
|
||||||
|
# Get basic weather data
|
||||||
|
VALUE_WEATHER_FORMAT=${weather_format:-"%c%f"}
|
||||||
|
VALUE_WEATHER_FORMAT="?format=${VALUE_WEATHER_FORMAT}"
|
||||||
|
WEATHER=$(curl -sS "https://wttr.in/${VALUE_WEATHER_LOCATION}${VALUE_WEATHER_FORMAT}${WEATHER_UNIT}" 2>/dev/null || echo "${VALUE_WEATHER_ERROR_MESSAGE}")
|
||||||
|
|
||||||
|
# Get sunrise/sunset data
|
||||||
|
VALUE_SUNSET_SUNRISE_FORMAT="?format=%S-%s"
|
||||||
|
SUNRISE_SUNSET=$(curl -sS "https://wttr.in/${VALUE_WEATHER_LOCATION}${VALUE_SUNSET_SUNRISE_FORMAT}${WEATHER_UNIT}" 2>/dev/null || echo "")
|
||||||
|
|
||||||
|
if [ -n "$SUNRISE_SUNSET" ]; then
|
||||||
|
SUNRISE_VALUE=$(echo ${SUNRISE_SUNSET} | cut -c 1-5)
|
||||||
|
SUNSET_VALUE=$(echo ${SUNRISE_SUNSET} | cut -c 7-11)
|
||||||
|
SUNRISE_SUNSET_TEXT=" (${SUNRISE_VALUE}-${SUNSET_VALUE})"
|
||||||
|
else
|
||||||
|
SUNRISE_SUNSET_TEXT=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check for errors
|
||||||
|
if echo "${WEATHER}" | grep -q -P "Unknown\slocation"; then
|
||||||
|
WEATHER=${VALUE_WEATHER_ERROR_MESSAGE}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Output for i3status-rust (plain text)
|
||||||
|
echo "${WEATHER}${SUNRISE_SUNSET_TEXT}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Handle click events (for i3status-rust custom block)
|
||||||
|
if [ "${BLOCK_BUTTON:-}" = "1" ]; then
|
||||||
|
# Left click - show detailed weather using JSON
|
||||||
|
DETAILED_WEATHER=$(curl -sS "https://wttr.in/${VALUE_WEATHER_LOCATION}?format=%l:+%c+%f+%h+%p+%P+%m+%w+%S-%s" 2>/dev/null || echo "${VALUE_WEATHER_ERROR_MESSAGE}")
|
||||||
|
notify-send "Weather Details" "$DETAILED_WEATHER" -t 10000
|
||||||
|
elif [ "${BLOCK_BUTTON:-}" = "3" ]; then
|
||||||
|
# Right click - open weather website
|
||||||
|
xdg-open "https://wttr.in/${VALUE_WEATHER_LOCATION}" >/dev/null 2>&1 &
|
||||||
|
fi
|
||||||
10
home_dotfiles/.config/sway/scripts/osrs/osrs-mode-status.sh
Executable file
10
home_dotfiles/.config/sway/scripts/osrs/osrs-mode-status.sh
Executable file
@@ -0,0 +1,10 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
MODE=$(swaymsg -r -t get_binding_state 2>/dev/null | jq -r '.name // "default"')
|
||||||
|
ICON=""
|
||||||
|
|
||||||
|
if [ "$MODE" = "OSRS" ]; then
|
||||||
|
echo "$ICON ON"
|
||||||
|
else
|
||||||
|
echo "$ICON OFF"
|
||||||
|
fi
|
||||||
10
home_dotfiles/.config/sway/scripts/osrs/osrs-mode-toggle.sh
Executable file
10
home_dotfiles/.config/sway/scripts/osrs/osrs-mode-toggle.sh
Executable file
@@ -0,0 +1,10 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
MODE_NAME="OSRS"
|
||||||
|
CURRENT=$(swaymsg -r -t get_binding_state 2>/dev/null | jq -r '.name // "default"')
|
||||||
|
|
||||||
|
if [ "$CURRENT" = "$MODE_NAME" ]; then
|
||||||
|
swaymsg mode default >/dev/null
|
||||||
|
else
|
||||||
|
swaymsg mode "$MODE_NAME" >/dev/null
|
||||||
|
fi
|
||||||
@@ -11,4 +11,4 @@ if [ "$muted" = "yes" ]; then
|
|||||||
notify-send -t 1000 "Volume" "Muted"
|
notify-send -t 1000 "Volume" "Muted"
|
||||||
else
|
else
|
||||||
notify-send -t 1000 "Volume" "$volume"
|
notify-send -t 1000 "Volume" "$volume"
|
||||||
fi
|
fi
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -Eeu -o pipefail
|
|
||||||
|
|
||||||
# Simplified weather script for i3status-rust
|
|
||||||
# Based on the original weather script but adapted for Sway/i3status-rust
|
|
||||||
|
|
||||||
# Information on the various formats: https://github.com/chubin/wttr.in
|
|
||||||
VALUE_WEATHER_FORMAT=${weather_format:-"%c%f"}
|
|
||||||
VALUE_WEATHER_FORMAT="?format=${VALUE_WEATHER_FORMAT}"
|
|
||||||
|
|
||||||
# Determine units to use for temperature
|
|
||||||
# We don't supply a default here because wttr.in is "smart" enough to choose for us
|
|
||||||
WEATHER_UNIT=${weather_unit:-""}
|
|
||||||
if [ -n "${WEATHER_UNIT}" ]; then
|
|
||||||
WEATHER_UNIT="&${WEATHER_UNIT}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Location (defaults to Pärnu as in your original script)
|
|
||||||
VALUE_WEATHER_LOCATION=${weather_location:-"Pärnu"}
|
|
||||||
VALUE_WEATHER_ERROR_MESSAGE=${error_message:-"⛔"}
|
|
||||||
VALUE_FETCH_WEATHER_URL="https://wttr.in/${VALUE_WEATHER_LOCATION}${VALUE_WEATHER_FORMAT}${WEATHER_UNIT}"
|
|
||||||
|
|
||||||
# Get weather data
|
|
||||||
WEATHER=$(curl -sS "$VALUE_FETCH_WEATHER_URL" 2>/dev/null || echo "${VALUE_WEATHER_ERROR_MESSAGE}")
|
|
||||||
|
|
||||||
# Get sunrise/sunset data
|
|
||||||
VALUE_SUNSET_SUNRISE_FORMAT="?format=%S-%s%20%m+"
|
|
||||||
SUNRISE_SUNSET=$(curl -sS "https://wttr.in/${VALUE_WEATHER_LOCATION}${VALUE_SUNSET_SUNRISE_FORMAT}${WEATHER_UNIT}" 2>/dev/null || echo "")
|
|
||||||
|
|
||||||
if [ -n "$SUNRISE_SUNSET" ]; then
|
|
||||||
SUNRISE_VALUE=$(echo ${SUNRISE_SUNSET} | cut -c 1-5)
|
|
||||||
SUNSET_VALUE=$(echo ${SUNRISE_SUNSET} | cut -c 10-14)
|
|
||||||
SUNRISE_SUNSET_TEXT=" (${SUNRISE_VALUE}-${SUNSET_VALUE})"
|
|
||||||
else
|
|
||||||
SUNRISE_SUNSET_TEXT=""
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check for errors
|
|
||||||
if echo "${WEATHER}" | grep -q -P "Unknown\slocation"; then
|
|
||||||
WEATHER=${VALUE_WEATHER_ERROR_MESSAGE}
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Output for i3status-rust (plain text)
|
|
||||||
echo "${WEATHER}${SUNRISE_SUNSET_TEXT}"
|
|
||||||
|
|
||||||
# Handle click events (for i3status-rust custom block)
|
|
||||||
if [ "${BLOCK_BUTTON:-}" = "1" ]; then
|
|
||||||
# Left click - show detailed weather
|
|
||||||
FULL_WEATHER=$(curl -sS "https://wttr.in/${VALUE_WEATHER_LOCATION}?format=%l:+%c+%f+%h+%p+%P+%m+%w+%S+%s" 2>/dev/null || echo "${VALUE_WEATHER_ERROR_MESSAGE}")
|
|
||||||
notify-send "Weather Details" "$FULL_WEATHER" -t 10000
|
|
||||||
elif [ "${BLOCK_BUTTON:-}" = "3" ]; then
|
|
||||||
# Right click - open weather website
|
|
||||||
xdg-open "https://wttr.in/${VALUE_WEATHER_LOCATION}" >/dev/null 2>&1 &
|
|
||||||
fi
|
|
||||||
4
home_dotfiles/.profile
Normal file
4
home_dotfiles/.profile
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
if [ -d "$HOME/.local/bin" ]; then
|
||||||
|
PATH="$HOME/.local/bin:$PATH"
|
||||||
|
fi
|
||||||
|
export PATH
|
||||||
@@ -149,3 +149,5 @@ alias info="pacman -Si "
|
|||||||
source /usr/share/nvm/init-nvm.sh
|
source /usr/share/nvm/init-nvm.sh
|
||||||
|
|
||||||
source ~/.aliases
|
source ~/.aliases
|
||||||
|
|
||||||
|
export JAVA_HOME=/usr/lib/jvm/java-21-temurin
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ echo "Installing Oh My Zsh and related requirements..."
|
|||||||
|
|
||||||
# Install base packages
|
# Install base packages
|
||||||
echo "Installing base packages..."
|
echo "Installing base packages..."
|
||||||
sudo pacman -S \
|
sudo pacman -S --needed \
|
||||||
zsh \
|
zsh \
|
||||||
git \
|
git \
|
||||||
curl \
|
curl \
|
||||||
|
|||||||
@@ -52,6 +52,16 @@ else
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Copy .profile to home directory
|
||||||
|
echo ""
|
||||||
|
print_status "Installing .profile configuration..."
|
||||||
|
if cp "$SCRIPT_DIR/.profile" ~/.profile; then
|
||||||
|
print_success ".profile installed to ~/.profile"
|
||||||
|
else
|
||||||
|
print_error "Failed to copy .profile"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
# Copy .aliases to home directory
|
# Copy .aliases to home directory
|
||||||
echo ""
|
echo ""
|
||||||
print_status "Installing .aliases configuration..."
|
print_status "Installing .aliases configuration..."
|
||||||
|
|||||||
BIN
home_dotfiles/wallpapers/1742471076220983.jpg
Executable file
BIN
home_dotfiles/wallpapers/1742471076220983.jpg
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 192 KiB |
2
install-arch-sway-requirements.sh
Normal file → Executable file
2
install-arch-sway-requirements.sh
Normal file → Executable file
@@ -159,7 +159,7 @@ echo " - Default location: Pärnu (wttr.in, no API key needed)"
|
|||||||
echo " - Shows weather + sunrise/sunset times"
|
echo " - Shows weather + sunrise/sunset times"
|
||||||
echo " - Left click: detailed weather notification"
|
echo " - Left click: detailed weather notification"
|
||||||
echo " - Right click: open wttr.in website"
|
echo " - Right click: open wttr.in website"
|
||||||
echo " - Change location: edit ~/.config/sway/weather-sway.sh"
|
echo " - Change location: edit ~/.config/sway/scripts/i3status/wttrin-weather.sh"
|
||||||
echo ""
|
echo ""
|
||||||
echo "3. Key applications configured:"
|
echo "3. Key applications configured:"
|
||||||
echo " - Terminal: foot"
|
echo " - Terminal: foot"
|
||||||
|
|||||||
@@ -47,33 +47,65 @@ echo "Installing i3status-rust config..."
|
|||||||
cp $SCRIPT_DIR/home_dotfiles/.config/sway/i3status-rust.toml ~/.config/sway/i3status-rust.toml
|
cp $SCRIPT_DIR/home_dotfiles/.config/sway/i3status-rust.toml ~/.config/sway/i3status-rust.toml
|
||||||
echo "✓ i3status-rust config installed to ~/.config/sway/i3status-rust.toml"
|
echo "✓ i3status-rust config installed to ~/.config/sway/i3status-rust.toml"
|
||||||
|
|
||||||
# === WEATHER SCRIPT ===
|
# === DISPLAY PROFILE TOGGLE (MODE / BAR HEIGHT / OUTPUT POSITION) ===
|
||||||
# Comment out this section if you don't want the weather script
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "Installing weather script..."
|
echo "Installing display profile toggle scripts/config..."
|
||||||
cp $SCRIPT_DIR/home_dotfiles/.config/sway/weather-sway.sh ~/.config/sway/weather-sway.sh
|
mkdir -p ~/.config/sway/scripts/display-profile
|
||||||
chmod +x ~/.config/sway/weather-sway.sh
|
for file in display-profile.conf display-profile-toggle.sh display-profile-status.sh; do
|
||||||
echo "✓ Weather script installed to ~/.config/sway/weather-sway.sh"
|
if [ -f "$SCRIPT_DIR/home_dotfiles/.config/sway/scripts/display-profile/$file" ]; then
|
||||||
|
cp "$SCRIPT_DIR/home_dotfiles/.config/sway/scripts/display-profile/$file" ~/.config/sway/scripts/display-profile/$file
|
||||||
|
case "$file" in
|
||||||
|
*.sh)
|
||||||
|
chmod +x ~/.config/sway/scripts/display-profile/$file
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
echo "✓ Installed ~/.config/sway/scripts/display-profile/$file"
|
||||||
|
else
|
||||||
|
echo "⚠ $file not found, skipping..."
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
# === BLUETOOTH SCRIPT ===
|
# === OSRS MODE SCRIPTS ===
|
||||||
echo ""
|
echo ""
|
||||||
echo "Installing bluetooth script..."
|
echo "Installing OSRS mode helper scripts..."
|
||||||
cp $SCRIPT_DIR/home_dotfiles/.config/sway/bluetooth-sway.sh ~/.config/sway/bluetooth-sway.sh
|
mkdir -p ~/.config/sway/scripts/osrs
|
||||||
chmod +x ~/.config/sway/bluetooth-sway.sh
|
for script in osrs-mode-status.sh osrs-mode-toggle.sh; do
|
||||||
echo "✓ Bluetooth script installed to ~/.config/sway/bluetooth-sway.sh"
|
if [ -f "$SCRIPT_DIR/home_dotfiles/.config/sway/scripts/osrs/$script" ]; then
|
||||||
|
cp "$SCRIPT_DIR/home_dotfiles/.config/sway/scripts/osrs/$script" ~/.config/sway/scripts/osrs/$script
|
||||||
|
chmod +x ~/.config/sway/scripts/osrs/$script
|
||||||
|
echo "✓ Installed ~/.config/sway/scripts/osrs/$script"
|
||||||
|
else
|
||||||
|
echo "⚠ $script not found, skipping..."
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
# === VOLUME NOTIFY SCRIPT ===
|
# === i3status BAR SCRIPTS ===
|
||||||
# Comment out this section if you don't want volume notifications
|
echo ""
|
||||||
if [ -f $SCRIPT_DIR/home_dotfiles/.config/sway/volume-notify-sway.sh ]; then
|
echo "Installing i3status bar scripts..."
|
||||||
echo ""
|
mkdir -p ~/.config/sway/scripts/i3status
|
||||||
echo "Installing volume notify script..."
|
for script in bluetooth.sh wttrin-weather.sh set-random-bg.sh get-focused-window.sh; do
|
||||||
cp $SCRIPT_DIR/home_dotfiles/.config/sway/volume-notify-sway.sh ~/.config/sway/volume-notify-sway.sh
|
if [ -f "$SCRIPT_DIR/home_dotfiles/.config/sway/scripts/i3status/$script" ]; then
|
||||||
chmod +x ~/.config/sway/volume-notify-sway.sh
|
cp "$SCRIPT_DIR/home_dotfiles/.config/sway/scripts/i3status/$script" ~/.config/sway/scripts/i3status/$script
|
||||||
echo "✓ Volume notify script installed to ~/.config/sway/volume-notify-sway.sh"
|
chmod +x ~/.config/sway/scripts/i3status/$script
|
||||||
else
|
echo "✓ Installed ~/.config/sway/scripts/i3status/$script"
|
||||||
echo ""
|
else
|
||||||
echo "⚠ volume-notify-sway.sh not found, skipping..."
|
echo "⚠ $script not found, skipping..."
|
||||||
fi
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# === SWAY CONFIG SCRIPTS ===
|
||||||
|
echo ""
|
||||||
|
echo "Installing sway config scripts..."
|
||||||
|
mkdir -p ~/.config/sway/scripts/sway
|
||||||
|
for script in volume-notify.sh; do
|
||||||
|
if [ -f "$SCRIPT_DIR/home_dotfiles/.config/sway/scripts/sway/$script" ]; then
|
||||||
|
cp "$SCRIPT_DIR/home_dotfiles/.config/sway/scripts/sway/$script" ~/.config/sway/scripts/sway/$script
|
||||||
|
chmod +x ~/.config/sway/scripts/sway/$script
|
||||||
|
echo "✓ Installed ~/.config/sway/scripts/sway/$script"
|
||||||
|
else
|
||||||
|
echo "⚠ $script not found, skipping..."
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
# === SET THUNAR AS DEFAULT FILE MANAGER ===
|
# === SET THUNAR AS DEFAULT FILE MANAGER ===
|
||||||
echo ""
|
echo ""
|
||||||
@@ -87,11 +119,22 @@ echo "Setting swayimg as default image viewer..."
|
|||||||
xdg-mime default swayimg.desktop image/jpeg image/jpg image/png image/gif image/webp image/bmp image/tiff image/svg+xml
|
xdg-mime default swayimg.desktop image/jpeg image/jpg image/png image/gif image/webp image/bmp image/tiff image/svg+xml
|
||||||
echo "✓ swayimg set as default image viewer"
|
echo "✓ swayimg set as default image viewer"
|
||||||
|
|
||||||
|
# === SET FIREFOX AS DEFAULT BROWSER ===
|
||||||
|
echo ""
|
||||||
|
echo "Setting Firefox as default browser..."
|
||||||
|
if command -v firefox >/dev/null 2>&1; then
|
||||||
|
xdg-settings set default-web-browser firefox.desktop
|
||||||
|
echo "✓ Firefox set as default browser"
|
||||||
|
else
|
||||||
|
echo "⚠ Firefox not installed, skipping default browser setup"
|
||||||
|
fi
|
||||||
|
|
||||||
# === SET WALLPAPER ===
|
# === SET WALLPAPER ===
|
||||||
echo ""
|
echo ""
|
||||||
echo "Setting wallpaper..."
|
echo "Setting wallpaper..."
|
||||||
#WALLPAPER_NAME="chris-czermak-PamFFHL6fVY-unsplash.jpg"
|
WALLPAPER_NAME="chris-czermak-PamFFHL6fVY-unsplash.jpg"
|
||||||
WALLPAPER_NAME="lucas-gallone-2dClJIAR404-unsplash.jpg"
|
#WALLPAPER_NAME="lucas-gallone-2dClJIAR404-unsplash.jpg"
|
||||||
|
#WALLPAPER_NAME="1742471076220983.jpg"
|
||||||
WALLPAPER_PATH="$SCRIPT_DIR/home_dotfiles/wallpapers/$WALLPAPER_NAME"
|
WALLPAPER_PATH="$SCRIPT_DIR/home_dotfiles/wallpapers/$WALLPAPER_NAME"
|
||||||
cp $WALLPAPER_PATH ~/.config/sway/wallpaper.jpg
|
cp $WALLPAPER_PATH ~/.config/sway/wallpaper.jpg
|
||||||
echo "✓ Wallpaper installed to ~/.config/sway/wallpaper.jpg"
|
echo "✓ Wallpaper installed to ~/.config/sway/wallpaper.jpg"
|
||||||
@@ -111,11 +154,14 @@ echo "- ~/.config/mako/config (notification styling)"
|
|||||||
echo "- ~/.config/sway/config (main Sway config)"
|
echo "- ~/.config/sway/config (main Sway config)"
|
||||||
echo "- ~/.config/swayimg/swayimgrc (image viewer config)"
|
echo "- ~/.config/swayimg/swayimgrc (image viewer config)"
|
||||||
echo "- ~/.config/sway/i3status-rust.toml (status bar config)"
|
echo "- ~/.config/sway/i3status-rust.toml (status bar config)"
|
||||||
echo "- ~/.config/sway/weather-sway.sh (weather script)"
|
echo "- ~/.config/sway/scripts/display-profile/display-profile.conf (display profile state/overrides)"
|
||||||
|
echo "- ~/.config/sway/scripts/display-profile/display-profile-toggle.sh (click-to-toggle display profile)"
|
||||||
|
echo "- ~/.config/sway/scripts/display-profile/display-profile-status.sh (status bar label for display profile)"
|
||||||
|
echo "- ~/.config/sway/scripts/i3status/wttrin-weather.sh (weather script)"
|
||||||
echo "- thunar set as default file manager"
|
echo "- thunar set as default file manager"
|
||||||
echo "- swayimg set as default image viewer"
|
echo "- swayimg set as default image viewer"
|
||||||
if [ -f ~/.config/sway/volume-notify-sway.sh ]; then
|
if [ -f ~/.config/sway/scripts/sway/volume-notify.sh ]; then
|
||||||
echo "- ~/.config/sway/volume-notify-sway.sh (volume notifications)"
|
echo "- ~/.config/sway/scripts/sway/volume-notify.sh (volume notifications)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
makoctl reload
|
makoctl reload
|
||||||
|
|||||||
10
scripts/git/git-commit-sign-prepare-gpg.sh
Normal file
10
scripts/git/git-commit-sign-prepare-gpg.sh
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
#gpg --full-generate-key
|
||||||
|
|
||||||
|
#gpg --list-secret-keys --keyid-format=long
|
||||||
|
|
||||||
|
#gpg --armor --export ..
|
||||||
|
|
||||||
|
#git config --global commit.gpgsign true
|
||||||
|
|
||||||
13
scripts/gpu/amd-gpu-performance.service
Normal file
13
scripts/gpu/amd-gpu-performance.service
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=AMD GPU High Performance Mode
|
||||||
|
After=multi-user.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
ExecStart=/bin/bash -c 'echo high > /sys/class/drm/card0/device/power_dpm_force_performance_level'
|
||||||
|
ExecStart=/bin/bash -c 'echo 2 > /sys/class/drm/card0/device/pp_dpm_sclk'
|
||||||
|
ExecStart=/bin/bash -c 'echo 3 > /sys/class/drm/card0/device/pp_dpm_mclk'
|
||||||
|
RemainAfterExit=yes
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
85
scripts/gpu/gpu-benchmark-fix.sh
Executable file
85
scripts/gpu/gpu-benchmark-fix.sh
Executable file
@@ -0,0 +1,85 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Comprehensive AMD GPU Performance Fix for Benchmarking
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
RED='\033[0:31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
echo -e "${GREEN}=== AMD RX 6900 XT Benchmark Performance Fix ===${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Find the AMD GPU
|
||||||
|
GPU_PATH=""
|
||||||
|
for card in /sys/class/drm/card[0-9]; do
|
||||||
|
if [ -f "$card/device/power_dpm_force_performance_level" ]; then
|
||||||
|
GPU_PATH="$card/device"
|
||||||
|
GPU_CARD=$(basename $(dirname $GPU_PATH))
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -z "$GPU_PATH" ]; then
|
||||||
|
echo -e "${RED}ERROR: Could not find AMD GPU!${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${GREEN}Found GPU at: $GPU_PATH${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Show current state
|
||||||
|
echo "=== BEFORE ==="
|
||||||
|
echo "Performance Level: $(cat $GPU_PATH/power_dpm_force_performance_level)"
|
||||||
|
echo "Core Clock:"
|
||||||
|
cat $GPU_PATH/pp_dpm_sclk | grep "\*"
|
||||||
|
echo "Memory Clock:"
|
||||||
|
cat $GPU_PATH/pp_dpm_mclk | grep "\*"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Apply fixes
|
||||||
|
echo -e "${YELLOW}Applying performance fixes...${NC}"
|
||||||
|
|
||||||
|
# 1. Set performance level to high
|
||||||
|
echo "high" | sudo tee $GPU_PATH/power_dpm_force_performance_level > /dev/null
|
||||||
|
echo "✓ Set performance level to HIGH"
|
||||||
|
|
||||||
|
# 2. Force highest core clock
|
||||||
|
echo "2" | sudo tee $GPU_PATH/pp_dpm_sclk > /dev/null
|
||||||
|
echo "✓ Forced highest core clock (2600MHz)"
|
||||||
|
|
||||||
|
# 3. Force highest memory clock
|
||||||
|
echo "3" | sudo tee $GPU_PATH/pp_dpm_mclk > /dev/null
|
||||||
|
echo "✓ Forced highest memory clock (2000MHz effective)"
|
||||||
|
|
||||||
|
# 4. Set power limit to maximum if available
|
||||||
|
if [ -f "$GPU_PATH/hwmon/hwmon*/power1_cap_max" ]; then
|
||||||
|
MAX_POWER=$(cat $GPU_PATH/hwmon/hwmon*/power1_cap_max)
|
||||||
|
echo "$MAX_POWER" | sudo tee $GPU_PATH/hwmon/hwmon*/power1_cap > /dev/null 2>&1
|
||||||
|
echo "✓ Set power limit to maximum"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== AFTER ==="
|
||||||
|
echo "Performance Level: $(cat $GPU_PATH/power_dpm_force_performance_level)"
|
||||||
|
echo "Core Clock:"
|
||||||
|
cat $GPU_PATH/pp_dpm_sclk | grep "\*"
|
||||||
|
echo "Memory Clock:"
|
||||||
|
cat $GPU_PATH/pp_dpm_mclk | grep "\*"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo -e "${GREEN}GPU is now at maximum performance!${NC}"
|
||||||
|
echo ""
|
||||||
|
echo -e "${YELLOW}Additional tips:${NC}"
|
||||||
|
echo "1. Close all background applications"
|
||||||
|
echo "2. Make sure Sway compositor isn't limiting FPS"
|
||||||
|
echo "3. Run benchmark in fullscreen mode"
|
||||||
|
echo "4. Check CPU governor is set to 'performance'"
|
||||||
|
echo ""
|
||||||
|
echo "To check CPU governor:"
|
||||||
|
echo " cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor | head -1"
|
||||||
|
echo ""
|
||||||
|
echo "To set CPU to performance mode:"
|
||||||
|
echo " echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor"
|
||||||
|
echo ""
|
||||||
|
echo -e "${GREEN}Now run your benchmark!${NC}"
|
||||||
59
scripts/gpu/gpu-performance-mode.sh
Executable file
59
scripts/gpu/gpu-performance-mode.sh
Executable file
@@ -0,0 +1,59 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Force AMD GPU to high performance mode for gaming/benchmarking
|
||||||
|
|
||||||
|
# Find the AMD GPU card (not integrated graphics)
|
||||||
|
GPU_PATH=""
|
||||||
|
for card in /sys/class/drm/card[0-9]; do
|
||||||
|
if [ -f "$card/device/power_dpm_force_performance_level" ]; then
|
||||||
|
GPU_PATH="$card/device"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -z "$GPU_PATH" ]; then
|
||||||
|
echo "ERROR: Could not find AMD GPU!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Found GPU at: $GPU_PATH"
|
||||||
|
|
||||||
|
echo "=== AMD GPU Performance Mode Script ==="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check current state
|
||||||
|
echo "Current settings:"
|
||||||
|
echo "Performance Level: $(cat $GPU_PATH/power_dpm_force_performance_level)"
|
||||||
|
echo ""
|
||||||
|
echo "Core Clock States:"
|
||||||
|
cat $GPU_PATH/pp_dpm_sclk
|
||||||
|
echo ""
|
||||||
|
echo "Memory Clock States:"
|
||||||
|
cat $GPU_PATH/pp_dpm_mclk
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Force high performance
|
||||||
|
echo "Forcing high performance mode..."
|
||||||
|
echo "high" | sudo tee $GPU_PATH/power_dpm_force_performance_level
|
||||||
|
|
||||||
|
# Force highest clock states
|
||||||
|
echo "Forcing maximum clock states..."
|
||||||
|
echo "2" | sudo tee $GPU_PATH/pp_dpm_sclk
|
||||||
|
echo "3" | sudo tee $GPU_PATH/pp_dpm_mclk
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== New settings ==="
|
||||||
|
echo "Performance Level: $(cat $GPU_PATH/power_dpm_force_performance_level)"
|
||||||
|
echo ""
|
||||||
|
echo "Core Clock States:"
|
||||||
|
cat $GPU_PATH/pp_dpm_sclk
|
||||||
|
echo ""
|
||||||
|
echo "Memory Clock States:"
|
||||||
|
cat $GPU_PATH/pp_dpm_mclk
|
||||||
|
echo ""
|
||||||
|
echo "GPU should now run at maximum performance!"
|
||||||
|
echo "Run your benchmark now."
|
||||||
|
echo ""
|
||||||
|
echo "To revert to auto mode, run:"
|
||||||
|
echo "echo 'auto' | sudo tee $GPU_PATH/power_dpm_force_performance_level"
|
||||||
|
|
||||||
|
|
||||||
12
scripts/osrs/autoclicker-stop.sh
Executable file
12
scripts/osrs/autoclicker-stop.sh
Executable file
@@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Script to stop the autoclicker
|
||||||
|
STATE_FILE="/tmp/autoclicker_running"
|
||||||
|
|
||||||
|
if [ -f "$STATE_FILE" ]; then
|
||||||
|
rm -f "$STATE_FILE"
|
||||||
|
echo "Autoclicker stop signal sent!"
|
||||||
|
else
|
||||||
|
echo "Autoclicker is not running."
|
||||||
|
fi
|
||||||
|
|
||||||
135
scripts/osrs/autoclicker.sh
Executable file
135
scripts/osrs/autoclicker.sh
Executable file
@@ -0,0 +1,135 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Autoclicker script for Sway
|
||||||
|
# Clicks continuously with random delays and periodic breaks
|
||||||
|
# Press ESC to stop
|
||||||
|
# Requires ydotool and ydotoold daemon running
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
MIN_DELAY=51 # Minimum delay in milliseconds
|
||||||
|
MAX_DELAY=689 # Maximum delay in milliseconds
|
||||||
|
MIN_CLICKS_BEFORE_BREAK=50 # Minimum clicks before break
|
||||||
|
MAX_CLICKS_BEFORE_BREAK=300 # Maximum clicks before break
|
||||||
|
MIN_BREAK=5 # Minimum break duration in seconds
|
||||||
|
MAX_BREAK=10 # Maximum break duration in seconds
|
||||||
|
|
||||||
|
STATE_FILE="/tmp/autoclicker_running"
|
||||||
|
LOCK_FILE="/tmp/autoclicker_lock"
|
||||||
|
|
||||||
|
# Check if ydotool is available
|
||||||
|
if ! command -v ydotool &> /dev/null; then
|
||||||
|
echo "Error: ydotool is not installed. Install it with: sudo pacman -S ydotool"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if bc is available (needed for random delay calculation)
|
||||||
|
if ! command -v bc &> /dev/null; then
|
||||||
|
echo "Error: bc is not installed. Install it with: sudo pacman -S bc"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if script is already running (prevent multiple instances)
|
||||||
|
if [ -f "$LOCK_FILE" ]; then
|
||||||
|
echo "Autoclicker is already running!"
|
||||||
|
echo "Press ESC to stop it."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create lock file
|
||||||
|
echo $$ > "$LOCK_FILE"
|
||||||
|
|
||||||
|
# Clean up lock file on exit
|
||||||
|
cleanup() {
|
||||||
|
rm -f "$LOCK_FILE"
|
||||||
|
rm -f "$STATE_FILE"
|
||||||
|
echo ""
|
||||||
|
echo "Autoclicker stopped."
|
||||||
|
}
|
||||||
|
trap cleanup EXIT INT TERM
|
||||||
|
|
||||||
|
# Check if ydotoold daemon is running
|
||||||
|
if ! pgrep -x "ydotoold" > /dev/null; then
|
||||||
|
echo "Starting ydotoold daemon..."
|
||||||
|
sudo ydotoold &
|
||||||
|
sleep 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create state file to indicate running
|
||||||
|
echo "running" > "$STATE_FILE"
|
||||||
|
|
||||||
|
# Function to generate random delay in seconds
|
||||||
|
get_random_delay() {
|
||||||
|
local min=$1
|
||||||
|
local max=$2
|
||||||
|
local range=$((max - min))
|
||||||
|
local random_ms=$((min + RANDOM % (range + 1)))
|
||||||
|
echo "scale=3; $random_ms / 1000" | bc
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to generate random number of clicks before break
|
||||||
|
get_random_clicks() {
|
||||||
|
local min=$1
|
||||||
|
local max=$2
|
||||||
|
local range=$((max - min))
|
||||||
|
echo $((min + RANDOM % (range + 1)))
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to check if ESC key was pressed (by checking if state file was removed)
|
||||||
|
check_exit() {
|
||||||
|
if [ ! -f "$STATE_FILE" ]; then
|
||||||
|
echo "Exit signal received!"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "=========================================="
|
||||||
|
echo "Autoclicker started!"
|
||||||
|
echo "=========================================="
|
||||||
|
echo "Configuration:"
|
||||||
|
echo " - Click delay: ${MIN_DELAY}-${MAX_DELAY}ms"
|
||||||
|
echo " - Break every: ${MIN_CLICKS_BEFORE_BREAK}-${MAX_CLICKS_BEFORE_BREAK} clicks (random)"
|
||||||
|
echo " - Break duration: ${MIN_BREAK}-${MAX_BREAK}s"
|
||||||
|
echo ""
|
||||||
|
echo "Press ESC or run: rm $STATE_FILE"
|
||||||
|
echo "=========================================="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
click_count=0
|
||||||
|
total_clicks=0
|
||||||
|
clicks_before_break=$(get_random_clicks $MIN_CLICKS_BEFORE_BREAK $MAX_CLICKS_BEFORE_BREAK)
|
||||||
|
echo "Next break will be after $clicks_before_break clicks"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
check_exit
|
||||||
|
|
||||||
|
# Generate random delay before this click
|
||||||
|
delay=$(get_random_delay $MIN_DELAY $MAX_DELAY)
|
||||||
|
|
||||||
|
# Perform click (suppress ydotool output)
|
||||||
|
ydotool click 0xC0 2>/dev/null
|
||||||
|
click_count=$((click_count + 1))
|
||||||
|
total_clicks=$((total_clicks + 1))
|
||||||
|
|
||||||
|
# Convert delay to milliseconds for display
|
||||||
|
delay_ms=$(echo "$delay * 1000" | bc | cut -d'.' -f1)
|
||||||
|
|
||||||
|
# Show each click with its delay
|
||||||
|
echo "Click #$total_clicks (delay: ${delay_ms}ms, next break in $((clicks_before_break - click_count)) clicks)"
|
||||||
|
|
||||||
|
# Check if it's time for a break
|
||||||
|
if [ $click_count -ge $clicks_before_break ]; then
|
||||||
|
break_duration=$(get_random_delay $((MIN_BREAK * 1000)) $((MAX_BREAK * 1000)))
|
||||||
|
echo ""
|
||||||
|
echo "[Break] Completed $clicks_before_break clicks (total: $total_clicks). Taking a break for ${break_duration}s..."
|
||||||
|
sleep "$break_duration"
|
||||||
|
click_count=0
|
||||||
|
# Generate new random click count for next cycle
|
||||||
|
clicks_before_break=$(get_random_clicks $MIN_CLICKS_BEFORE_BREAK $MAX_CLICKS_BEFORE_BREAK)
|
||||||
|
echo "[Resumed] Next break will be after $clicks_before_break clicks"
|
||||||
|
echo ""
|
||||||
|
else
|
||||||
|
# Wait the random delay before next click
|
||||||
|
sleep "$delay"
|
||||||
|
fi
|
||||||
|
done
|
||||||
235
scripts/osrs/autoclicker/autoclicker-enhanced.sh
Executable file
235
scripts/osrs/autoclicker/autoclicker-enhanced.sh
Executable file
@@ -0,0 +1,235 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Enhanced Autoclicker script for Sway with improved antiban features
|
||||||
|
# Uses ydotool for Wayland/Sway environments
|
||||||
|
# Features human-like timing patterns and CSV logging for visualization
|
||||||
|
# Press Ctrl+C to stop (standard shell interrupt)
|
||||||
|
# Requires ydotool and ydotoold daemon running
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
MIN_DELAY=50 # Minimum delay in milliseconds
|
||||||
|
MAX_DELAY=700 # Maximum delay in milliseconds
|
||||||
|
MIN_CLICKS_BEFORE_BREAK=30 # Minimum clicks before break
|
||||||
|
MAX_CLICKS_BEFORE_BREAK=200 # Maximum clicks before break
|
||||||
|
MIN_BREAK=3 # Minimum break duration in seconds
|
||||||
|
MAX_BREAK=15 # Maximum break duration in seconds
|
||||||
|
|
||||||
|
# Human-like timing parameters
|
||||||
|
FASTIGUE_FACTOR=0.95 # Gradually slow down over time (0.95 = 5% slower)
|
||||||
|
REACTION_VARIATION=0.3 # 30% variation in reaction times
|
||||||
|
PATTERN_BREAK_CHANCE=0.05 # 5% chance to break pattern
|
||||||
|
|
||||||
|
# File paths
|
||||||
|
STATE_FILE="/tmp/autoclicker_running"
|
||||||
|
LOCK_FILE="/tmp/autoclicker_lock"
|
||||||
|
LOG_DIR="/tmp/autoclicker_logs"
|
||||||
|
LOG_FILE="$LOG_DIR/click_timings_$(date +%Y%m%d_%H%M%S).csv"
|
||||||
|
|
||||||
|
# Create log directory if it doesn't exist
|
||||||
|
mkdir -p "$LOG_DIR"
|
||||||
|
|
||||||
|
# Initialize CSV log file with header
|
||||||
|
echo "click_number,delay_ms,timestamp" > "$LOG_FILE"
|
||||||
|
|
||||||
|
# Check if ydotool is available
|
||||||
|
if ! command -v ydotool &> /dev/null; then
|
||||||
|
echo "Error: ydotool is not installed. Install it with: sudo pacman -S ydotool"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if bc is available (needed for calculations)
|
||||||
|
if ! command -v bc &> /dev/null; then
|
||||||
|
echo "Error: bc is not installed. Install it with: sudo pacman -S bc"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if script is already running (prevent multiple instances)
|
||||||
|
if [ -f "$LOCK_FILE" ]; then
|
||||||
|
echo "Autoclicker is already running!"
|
||||||
|
echo "Press Ctrl+C in the terminal where it's running to stop it."
|
||||||
|
# Clean up the incomplete log file that was just created
|
||||||
|
rm -f "$LOG_FILE"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create lock file
|
||||||
|
echo $$ > "$LOCK_FILE"
|
||||||
|
|
||||||
|
# Global exit flag
|
||||||
|
EXIT_REQUESTED=0
|
||||||
|
|
||||||
|
# Clean up on exit
|
||||||
|
cleanup() {
|
||||||
|
EXIT_REQUESTED=1
|
||||||
|
rm -f "$LOCK_FILE"
|
||||||
|
rm -f "$STATE_FILE"
|
||||||
|
echo ""
|
||||||
|
echo "Autoclicker stopped."
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Set up traps for cleanup
|
||||||
|
trap cleanup INT TERM
|
||||||
|
|
||||||
|
# Check if ydotoold daemon is running
|
||||||
|
if ! pgrep -x "ydotoold" > /dev/null; then
|
||||||
|
echo "Starting ydotoold daemon..."
|
||||||
|
sudo ydotoold &
|
||||||
|
sleep 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create state file to indicate running
|
||||||
|
echo "running" > "$STATE_FILE"
|
||||||
|
|
||||||
|
# Function to log click timing to CSV
|
||||||
|
log_click_timing() {
|
||||||
|
local click_number=$1
|
||||||
|
local delay_ms=$2
|
||||||
|
local timestamp=$(date +%s%3N) # Milliseconds since epoch
|
||||||
|
echo "$click_number,$delay_ms,$timestamp" >> "$LOG_FILE"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to generate random delay with human-like distribution
|
||||||
|
get_human_delay() {
|
||||||
|
local min=$1
|
||||||
|
local max=$2
|
||||||
|
local base_delay=$((min + RANDOM % (max - min + 1)))
|
||||||
|
|
||||||
|
# Apply reaction time variation (30% up or down)
|
||||||
|
local variation=$(echo "scale=3; $base_delay * $REACTION_VARIATION * (2 * $RANDOM / 32767 - 1)" | bc)
|
||||||
|
local varied_delay=$(echo "$base_delay + $variation" | bc)
|
||||||
|
|
||||||
|
# Ensure we stay within reasonable bounds
|
||||||
|
if (( $(echo "$varied_delay < $min" | bc -l) )); then
|
||||||
|
varied_delay=$min
|
||||||
|
elif (( $(echo "$varied_delay > $max" | bc -l) )); then
|
||||||
|
varied_delay=$max
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Convert to seconds for sleep function
|
||||||
|
echo "scale=3; $varied_delay / 1000" | bc
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to generate random number of clicks before break
|
||||||
|
get_random_clicks() {
|
||||||
|
local min=$1
|
||||||
|
local max=$2
|
||||||
|
echo $((min + RANDOM % (max - min + 1)))
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to sleep with interrupt checking
|
||||||
|
interruptible_sleep() {
|
||||||
|
local duration=$1
|
||||||
|
local start_time=$(date +%s.%N)
|
||||||
|
local end_time=$(echo "$start_time + $duration" | bc)
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
if [ $EXIT_REQUESTED -eq 1 ]; then
|
||||||
|
return 1 # Exit requested
|
||||||
|
fi
|
||||||
|
|
||||||
|
local current_time=$(date +%s.%N)
|
||||||
|
if (( $(echo "$current_time >= $end_time" | bc -l) )); then
|
||||||
|
return 0 # Sleep completed
|
||||||
|
fi
|
||||||
|
|
||||||
|
sleep 0.1
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to apply fatigue effect (gradually slow down)
|
||||||
|
apply_fatigue() {
|
||||||
|
local current_delay=$1
|
||||||
|
local click_count=$2
|
||||||
|
local fatigue_effect=$(echo "scale=3; $current_delay * (1 + $FASTIGUE_FACTOR * $click_count / 1000)" | bc)
|
||||||
|
echo "$fatigue_effect"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to randomly break pattern (5% chance)
|
||||||
|
should_break_pattern() {
|
||||||
|
local threshold=$(echo "$PATTERN_BREAK_CHANCE * 32767" | bc | cut -d'.' -f1)
|
||||||
|
[ $RANDOM -lt $threshold ]
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "=========================================="
|
||||||
|
echo "Enhanced Autoclicker started!"
|
||||||
|
echo "=========================================="
|
||||||
|
echo "Configuration:"
|
||||||
|
echo " - Click delay: ${MIN_DELAY}-${MAX_DELAY}ms (human-like variation)"
|
||||||
|
echo " - Break every: ${MIN_CLICKS_BEFORE_BREAK}-${MAX_CLICKS_BEFORE_BREAK} clicks (random)"
|
||||||
|
echo " - Break duration: ${MIN_BREAK}-${MAX_BREAK}s"
|
||||||
|
echo " - Fatigue factor: ${FASTIGUE_FACTOR} (gradual slowdown)"
|
||||||
|
echo " - Pattern break chance: ${PATTERN_BREAK_CHANCE} (5%)"
|
||||||
|
echo " - Logging to: $LOG_FILE"
|
||||||
|
echo ""
|
||||||
|
echo "Press Ctrl+C to stop"
|
||||||
|
echo "=========================================="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
click_count=0
|
||||||
|
total_clicks=0
|
||||||
|
clicks_before_break=$(get_random_clicks $MIN_CLICKS_BEFORE_BREAK $MAX_CLICKS_BEFORE_BREAK)
|
||||||
|
echo "Next break will be after $clicks_before_break clicks"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
if [ $EXIT_REQUESTED -eq 1 ]; then
|
||||||
|
echo "Exit signal received!"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Generate base random delay
|
||||||
|
base_delay=$(get_human_delay $MIN_DELAY $MAX_DELAY)
|
||||||
|
|
||||||
|
# Apply fatigue effect (gradually slow down)
|
||||||
|
final_delay=$(apply_fatigue "$base_delay" "$click_count")
|
||||||
|
|
||||||
|
# Randomly break pattern (5% chance)
|
||||||
|
if should_break_pattern; then
|
||||||
|
# Add a longer, unpredictable delay
|
||||||
|
pattern_break_delay=$(echo "scale=3; ($MAX_DELAY * 2 + $RANDOM % 1000) / 1000" | bc)
|
||||||
|
echo "[Pattern Break] Adding unpredictable delay of $(echo "$pattern_break_delay * 1000" | bc | cut -d'.' -f1)ms"
|
||||||
|
|
||||||
|
if ! interruptible_sleep "$pattern_break_delay"; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Perform click (suppress ydotool output)
|
||||||
|
ydotool click 0xC0 2>/dev/null
|
||||||
|
click_count=$((click_count + 1))
|
||||||
|
total_clicks=$((total_clicks + 1))
|
||||||
|
|
||||||
|
# Convert delay to milliseconds for display
|
||||||
|
delay_ms=$(echo "$final_delay * 1000" | bc | cut -d'.' -f1)
|
||||||
|
|
||||||
|
# Log click timing to CSV
|
||||||
|
log_click_timing "$total_clicks" "$delay_ms"
|
||||||
|
|
||||||
|
# Show each click with its delay
|
||||||
|
echo "Click #$total_clicks (delay: ${delay_ms}ms, next break in $((clicks_before_break - click_count)) clicks)"
|
||||||
|
|
||||||
|
# Check if it's time for a break
|
||||||
|
if [ $click_count -ge $clicks_before_break ]; then
|
||||||
|
break_duration=$(get_human_delay $((MIN_BREAK * 1000)) $((MAX_BREAK * 1000)))
|
||||||
|
echo ""
|
||||||
|
echo "[Break] Completed $clicks_before_break clicks (total: $total_clicks). Taking a break for ${break_duration}s..."
|
||||||
|
|
||||||
|
if ! interruptible_sleep "$break_duration"; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
|
||||||
|
click_count=0
|
||||||
|
# Generate new random click count for next cycle
|
||||||
|
clicks_before_break=$(get_random_clicks $MIN_CLICKS_BEFORE_BREAK $MAX_CLICKS_BEFORE_BREAK)
|
||||||
|
echo "[Resumed] Next break will be after $clicks_before_break clicks"
|
||||||
|
echo ""
|
||||||
|
else
|
||||||
|
# Wait the calculated delay before next click
|
||||||
|
if ! interruptible_sleep "$final_delay"; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Click timings saved to: $LOG_FILE"
|
||||||
619
scripts/osrs/autoclicker/click-visualizer.html
Normal file
619
scripts/osrs/autoclicker/click-visualizer.html
Normal file
@@ -0,0 +1,619 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Autoclicker Timing Visualizer</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||||
|
margin: 0;
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
max-width: 1200px;
|
||||||
|
margin: 0 auto;
|
||||||
|
background-color: white;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
color: #2c3e50;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.controls {
|
||||||
|
display: flex;
|
||||||
|
gap: 15px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-group {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 250px;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #2c3e50;
|
||||||
|
}
|
||||||
|
|
||||||
|
input, select, button {
|
||||||
|
padding: 8px 12px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
background-color: #3498db;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:hover {
|
||||||
|
background-color: #2980b9;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:disabled {
|
||||||
|
background-color: #95a5a6;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats {
|
||||||
|
display: flex;
|
||||||
|
gap: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-card {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 200px;
|
||||||
|
background-color: #ecf0f1;
|
||||||
|
padding: 15px;
|
||||||
|
border-radius: 6px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-value {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #2c3e50;
|
||||||
|
margin: 5px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-label {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #7f8c8d;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-container {
|
||||||
|
background-color: white;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 15px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
|
||||||
|
position: relative;
|
||||||
|
height: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-title {
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
color: #2c3e50;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-wrapper {
|
||||||
|
position: relative;
|
||||||
|
height: 300px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-list {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-item {
|
||||||
|
padding: 10px;
|
||||||
|
border-bottom: 1px solid #eee;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-item:hover {
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-item.active {
|
||||||
|
background-color: #e3f2fd;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-name {
|
||||||
|
color: #3498db;
|
||||||
|
margin-bottom: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-info {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #7f8c8d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading {
|
||||||
|
text-align: center;
|
||||||
|
padding: 20px;
|
||||||
|
color: #7f8c8d;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error {
|
||||||
|
color: #e74c3c;
|
||||||
|
padding: 10px;
|
||||||
|
background-color: #fadbd8;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.server-info {
|
||||||
|
background-color: #e8f5e9;
|
||||||
|
padding: 15px;
|
||||||
|
border-radius: 6px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
border-left: 4px solid #4caf50;
|
||||||
|
}
|
||||||
|
|
||||||
|
.api-status {
|
||||||
|
background-color: #fff3cd;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.api-status.success {
|
||||||
|
background-color: #d4edda;
|
||||||
|
color: #155724;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.api-status.error {
|
||||||
|
background-color: #f8d7da;
|
||||||
|
color: #721c24;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.controls, .stats {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<h1>🖱️ Autoclicker Timing Visualizer</h1>
|
||||||
|
|
||||||
|
<div class="server-info">
|
||||||
|
<strong>📊 Real-time Data Server</strong>
|
||||||
|
<p>This visualizer connects to a local Python server that serves real log files from <code>/tmp/autoclicker_logs/</code></p>
|
||||||
|
<p>Make sure to run: <code>python3 click_server.py</code> in a separate terminal</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="apiStatus" class="api-status">
|
||||||
|
Testing API connection...
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="controls">
|
||||||
|
<div class="control-group">
|
||||||
|
<label for="logFile">Select Log File:</label>
|
||||||
|
<select id="logFile">
|
||||||
|
<option value="">-- Loading log files... --</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="control-group">
|
||||||
|
<label for="chartType">Chart Type:</label>
|
||||||
|
<select id="chartType">
|
||||||
|
<option value="scatter">Scatter Plot</option>
|
||||||
|
<option value="line">Line Chart</option>
|
||||||
|
<option value="histogram">Histogram</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="control-group">
|
||||||
|
<label> </label>
|
||||||
|
<button id="loadBtn" disabled>Load Data</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stats" id="statsContainer" style="display: none;">
|
||||||
|
<div class="stat-card">
|
||||||
|
<div class="stat-label">Total Clicks</div>
|
||||||
|
<div class="stat-value" id="totalClicks">0</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-card">
|
||||||
|
<div class="stat-label">Average Delay</div>
|
||||||
|
<div class="stat-value" id="avgDelay">0 ms</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-card">
|
||||||
|
<div class="stat-label">Min Delay</div>
|
||||||
|
<div class="stat-value" id="minDelay">0 ms</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-card">
|
||||||
|
<div class="stat-label">Max Delay</div>
|
||||||
|
<div class="stat-value" id="maxDelay">0 ms</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-card">
|
||||||
|
<div class="stat-label">Std Deviation</div>
|
||||||
|
<div class="stat-value" id="stdDev">0 ms</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="chart-container">
|
||||||
|
<div class="chart-title">Click Timing Distribution</div>
|
||||||
|
<div class="chart-wrapper">
|
||||||
|
<canvas id="timingChart"></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="chart-container">
|
||||||
|
<div class="chart-title">Delay Over Time</div>
|
||||||
|
<div class="chart-wrapper">
|
||||||
|
<canvas id="timeSeriesChart"></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="file-list">
|
||||||
|
<h3>Available Log Files</h3>
|
||||||
|
<div id="fileList">
|
||||||
|
<div class="loading">Loading log files from server...</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Load Chart.js with date adapter -->
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns@3.0.0"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Global variables
|
||||||
|
let clickData = [];
|
||||||
|
let timingChart, timeSeriesChart;
|
||||||
|
let currentFile = '';
|
||||||
|
|
||||||
|
// API base URL
|
||||||
|
const API_BASE = '/api';
|
||||||
|
|
||||||
|
// DOM elements
|
||||||
|
const logFileSelect = document.getElementById('logFile');
|
||||||
|
const chartTypeSelect = document.getElementById('chartType');
|
||||||
|
const loadBtn = document.getElementById('loadBtn');
|
||||||
|
const fileList = document.getElementById('fileList');
|
||||||
|
const statsContainer = document.getElementById('statsContainer');
|
||||||
|
const apiStatus = document.getElementById('apiStatus');
|
||||||
|
|
||||||
|
// Test API connection
|
||||||
|
async function testAPIConnection() {
|
||||||
|
try {
|
||||||
|
const response = await fetch(`${API_BASE}/logs`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
'Accept': 'application/json'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
apiStatus.textContent = "✅ API connected successfully!";
|
||||||
|
apiStatus.className = "api-status success";
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
throw new Error(`HTTP ${response.status}`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
apiStatus.textContent = `❌ API connection failed: ${error.message}. Is the Python server running?`;
|
||||||
|
apiStatus.className = "api-status error";
|
||||||
|
console.error('API connection error:', error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize charts with proper configuration
|
||||||
|
function initCharts() {
|
||||||
|
const timingCtx = document.getElementById('timingChart').getContext('2d');
|
||||||
|
const timeSeriesCtx = document.getElementById('timeSeriesChart').getContext('2d');
|
||||||
|
|
||||||
|
// Destroy existing charts if they exist
|
||||||
|
if (timingChart) timingChart.destroy();
|
||||||
|
if (timeSeriesChart) timeSeriesChart.destroy();
|
||||||
|
|
||||||
|
timingChart = new Chart(timingCtx, {
|
||||||
|
type: 'scatter',
|
||||||
|
data: { datasets: [] },
|
||||||
|
options: {
|
||||||
|
responsive: true,
|
||||||
|
maintainAspectRatio: false,
|
||||||
|
scales: {
|
||||||
|
x: {
|
||||||
|
type: 'linear',
|
||||||
|
title: { display: true, text: 'Click Number' }
|
||||||
|
},
|
||||||
|
y: {
|
||||||
|
type: 'linear',
|
||||||
|
title: { display: true, text: 'Delay (ms)' }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
plugins: {
|
||||||
|
tooltip: {
|
||||||
|
callbacks: {
|
||||||
|
label: function(context) {
|
||||||
|
return `Click ${context.raw.x}: ${context.raw.y}ms`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
timeSeriesChart = new Chart(timeSeriesCtx, {
|
||||||
|
type: 'line',
|
||||||
|
data: { datasets: [] },
|
||||||
|
options: {
|
||||||
|
responsive: true,
|
||||||
|
maintainAspectRatio: false,
|
||||||
|
scales: {
|
||||||
|
x: {
|
||||||
|
type: 'linear',
|
||||||
|
title: { display: true, text: 'Click Number' }
|
||||||
|
},
|
||||||
|
y: {
|
||||||
|
type: 'linear',
|
||||||
|
title: { display: true, text: 'Delay (ms)' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load available log files from server
|
||||||
|
async function loadLogFiles() {
|
||||||
|
try {
|
||||||
|
fileList.innerHTML = '<div class="loading">Loading log files...</div>';
|
||||||
|
logFileSelect.innerHTML = '<option value="">-- Loading... --</option>';
|
||||||
|
|
||||||
|
const response = await fetch(`${API_BASE}/logs`);
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`Server error: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
if (data.error) {
|
||||||
|
throw new Error(data.error);
|
||||||
|
}
|
||||||
|
|
||||||
|
const files = data.logs;
|
||||||
|
|
||||||
|
if (files.length === 0) {
|
||||||
|
fileList.innerHTML = '<div class="error">No log files found. Run the enhanced autoclicker first.</div>';
|
||||||
|
logFileSelect.innerHTML = '<option value="">-- No log files available --</option>';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Populate select dropdown
|
||||||
|
logFileSelect.innerHTML = '<option value="">-- Select a log file --</option>';
|
||||||
|
files.forEach(file => {
|
||||||
|
const option = document.createElement('option');
|
||||||
|
option.value = file.name;
|
||||||
|
option.textContent = `${file.name} (${file.date})`;
|
||||||
|
logFileSelect.appendChild(option);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Populate file list
|
||||||
|
fileList.innerHTML = files.map(file => `
|
||||||
|
<div class="file-item" data-file="${file.name}">
|
||||||
|
<div class="file-name">${file.name}</div>
|
||||||
|
<div class="file-info">Size: ${file.size} | Created: ${file.date}</div>
|
||||||
|
</div>
|
||||||
|
`).join('');
|
||||||
|
|
||||||
|
// Add click handlers to file items
|
||||||
|
document.querySelectorAll('.file-item').forEach(item => {
|
||||||
|
item.addEventListener('click', function() {
|
||||||
|
document.querySelectorAll('.file-item').forEach(i => i.classList.remove('active'));
|
||||||
|
this.classList.add('active');
|
||||||
|
logFileSelect.value = this.dataset.file;
|
||||||
|
loadBtn.disabled = false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error loading log files:', error);
|
||||||
|
fileList.innerHTML = `<div class="error">Error loading log files: ${error.message}</div>`;
|
||||||
|
logFileSelect.innerHTML = '<option value="">-- Error loading files --</option>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load and parse JSON data from server
|
||||||
|
async function loadData() {
|
||||||
|
const fileName = logFileSelect.value;
|
||||||
|
if (!fileName) return;
|
||||||
|
|
||||||
|
currentFile = fileName;
|
||||||
|
loadBtn.disabled = true;
|
||||||
|
loadBtn.textContent = 'Loading...';
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(`${API_BASE}/log/${encodeURIComponent(fileName)}`);
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`Server error: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
if (data.error) {
|
||||||
|
if (data.content_preview) {
|
||||||
|
fileList.innerHTML = `<div class="error">Invalid JSON in ${fileName}: ${data.error}<br><br>File content preview:<pre>${data.content_preview}</pre></div>`;
|
||||||
|
} else {
|
||||||
|
fileList.innerHTML = `<div class="error">Error loading ${fileName}: ${data.error}</div>`;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!data.valid) {
|
||||||
|
fileList.innerHTML = `<div class="error">File ${fileName} is not valid JSON: ${data.error || 'Unknown error'}</div>`;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
clickData = data.data;
|
||||||
|
updateCharts();
|
||||||
|
updateStats();
|
||||||
|
statsContainer.style.display = 'flex';
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error loading data:', error);
|
||||||
|
fileList.innerHTML = `<div class="error">Error loading ${fileName}: ${error.message}</div>`;
|
||||||
|
} finally {
|
||||||
|
loadBtn.disabled = false;
|
||||||
|
loadBtn.textContent = 'Load Data';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update charts with current data
|
||||||
|
function updateCharts() {
|
||||||
|
if (clickData.length === 0) return;
|
||||||
|
|
||||||
|
// Update timing chart based on selected type
|
||||||
|
const chartType = chartTypeSelect.value;
|
||||||
|
|
||||||
|
if (chartType === 'scatter' || chartType === 'line') {
|
||||||
|
const dataPoints = clickData.map(item => ({
|
||||||
|
x: item.click,
|
||||||
|
y: item.delay_ms
|
||||||
|
}));
|
||||||
|
|
||||||
|
timingChart.data.datasets = [{
|
||||||
|
label: 'Click Delays',
|
||||||
|
data: dataPoints,
|
||||||
|
type: chartType,
|
||||||
|
backgroundColor: 'rgba(52, 152, 219, 0.5)',
|
||||||
|
borderColor: 'rgba(52, 152, 219, 1)',
|
||||||
|
pointRadius: chartType === 'scatter' ? 4 : 2,
|
||||||
|
tension: chartType === 'line' ? 0.3 : 0,
|
||||||
|
pointStyle: 'circle'
|
||||||
|
}];
|
||||||
|
timingChart.update();
|
||||||
|
} else if (chartType === 'histogram') {
|
||||||
|
// Create histogram data
|
||||||
|
const delays = clickData.map(item => item.delay_ms);
|
||||||
|
const bins = createHistogram(delays, 20);
|
||||||
|
const histogramData = bins.map((count, i) => ({
|
||||||
|
x: i * (700 / 20) + 50,
|
||||||
|
y: count
|
||||||
|
}));
|
||||||
|
|
||||||
|
timingChart.data.datasets = [{
|
||||||
|
label: 'Delay Distribution',
|
||||||
|
data: histogramData,
|
||||||
|
type: 'bar',
|
||||||
|
backgroundColor: 'rgba(52, 152, 219, 0.7)',
|
||||||
|
borderColor: 'rgba(52, 152, 219, 1)',
|
||||||
|
barPercentage: 0.9
|
||||||
|
}];
|
||||||
|
timingChart.options.scales.x.title.text = 'Delay Range (ms)';
|
||||||
|
timingChart.options.scales.y.title.text = 'Frequency';
|
||||||
|
timingChart.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update time series chart (using click number instead of time for simplicity)
|
||||||
|
const timeSeriesData = clickData.map(item => ({
|
||||||
|
x: item.click,
|
||||||
|
y: item.delay_ms
|
||||||
|
}));
|
||||||
|
|
||||||
|
timeSeriesChart.data.datasets = [{
|
||||||
|
label: 'Delay Over Time',
|
||||||
|
data: timeSeriesData,
|
||||||
|
borderColor: 'rgba(46, 204, 113, 1)',
|
||||||
|
backgroundColor: 'rgba(46, 204, 113, 0.1)',
|
||||||
|
tension: 0.3,
|
||||||
|
pointRadius: 2,
|
||||||
|
pointStyle: 'circle'
|
||||||
|
}];
|
||||||
|
timeSeriesChart.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create histogram from data
|
||||||
|
function createHistogram(data, binCount) {
|
||||||
|
if (data.length === 0) return [];
|
||||||
|
|
||||||
|
const min = Math.min(...data);
|
||||||
|
const max = Math.max(...data);
|
||||||
|
const binSize = (max - min) / binCount;
|
||||||
|
const bins = new Array(binCount).fill(0);
|
||||||
|
|
||||||
|
data.forEach(value => {
|
||||||
|
const binIndex = Math.min(Math.floor((value - min) / binSize), binCount - 1);
|
||||||
|
bins[binIndex]++;
|
||||||
|
});
|
||||||
|
|
||||||
|
return bins;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update statistics
|
||||||
|
function updateStats() {
|
||||||
|
if (clickData.length === 0) return;
|
||||||
|
|
||||||
|
const delays = clickData.map(item => item.delay_ms);
|
||||||
|
const total = delays.length;
|
||||||
|
const sum = delays.reduce((a, b) => a + b, 0);
|
||||||
|
const avg = sum / total;
|
||||||
|
const min = Math.min(...delays);
|
||||||
|
const max = Math.max(...delays);
|
||||||
|
|
||||||
|
// Calculate standard deviation
|
||||||
|
const variance = delays.reduce((sq, n) => sq + Math.pow(n - avg, 2), 0) / total;
|
||||||
|
const stdDev = Math.sqrt(variance);
|
||||||
|
|
||||||
|
document.getElementById('totalClicks').textContent = total;
|
||||||
|
document.getElementById('avgDelay').textContent = `${avg.toFixed(1)} ms`;
|
||||||
|
document.getElementById('minDelay').textContent = `${min} ms`;
|
||||||
|
document.getElementById('maxDelay').textContent = `${max} ms`;
|
||||||
|
document.getElementById('stdDev').textContent = `${stdDev.toFixed(1)} ms`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Event listeners
|
||||||
|
logFileSelect.addEventListener('change', function() {
|
||||||
|
loadBtn.disabled = !this.value;
|
||||||
|
});
|
||||||
|
|
||||||
|
chartTypeSelect.addEventListener('change', updateCharts);
|
||||||
|
|
||||||
|
loadBtn.addEventListener('click', loadData);
|
||||||
|
|
||||||
|
// Initialize
|
||||||
|
initCharts();
|
||||||
|
|
||||||
|
// Test API connection first
|
||||||
|
testAPIConnection().then(isConnected => {
|
||||||
|
if (isConnected) {
|
||||||
|
loadLogFiles();
|
||||||
|
// Auto-refresh log list every 10 seconds
|
||||||
|
setInterval(loadLogFiles, 10000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
183
scripts/osrs/autoclicker/click_server.py
Executable file
183
scripts/osrs/autoclicker/click_server.py
Executable file
@@ -0,0 +1,183 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
"""
|
||||||
|
Simple web server for autoclicker visualization
|
||||||
|
Serves the HTML visualizer and provides API endpoints for CSV log files
|
||||||
|
Converts CSV to JSON for the frontend
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
import csv
|
||||||
|
import http.server
|
||||||
|
import socketserver
|
||||||
|
from urllib.parse import urlparse, parse_qs
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
PORT = 8661
|
||||||
|
LOG_DIR = "/tmp/autoclicker_logs"
|
||||||
|
|
||||||
|
class ClickServerHandler(http.server.SimpleHTTPRequestHandler):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, directory=".", **kwargs)
|
||||||
|
|
||||||
|
def do_GET(self):
|
||||||
|
# Handle API requests
|
||||||
|
if self.path.startswith('/api/'):
|
||||||
|
self.handle_api_request()
|
||||||
|
return
|
||||||
|
|
||||||
|
# Serve the visualizer HTML for root path
|
||||||
|
if self.path == '/' or self.path == '/index.html':
|
||||||
|
self.path = '/click-visualizer.html'
|
||||||
|
|
||||||
|
# Serve static files normally
|
||||||
|
return super().do_GET()
|
||||||
|
|
||||||
|
def handle_api_request(self):
|
||||||
|
"""Handle API endpoints for log file operations"""
|
||||||
|
try:
|
||||||
|
if self.path.startswith('/api/logs'):
|
||||||
|
self.handle_logs_request()
|
||||||
|
elif self.path.startswith('/api/log/'):
|
||||||
|
self.handle_log_file_request()
|
||||||
|
else:
|
||||||
|
self.send_error(404, "API endpoint not found")
|
||||||
|
except Exception as e:
|
||||||
|
self.send_error(500, f"Server error: {str(e)}")
|
||||||
|
|
||||||
|
def handle_logs_request(self):
|
||||||
|
"""Return list of available log files"""
|
||||||
|
if not os.path.exists(LOG_DIR):
|
||||||
|
self.send_json_response({"error": "Log directory not found", "logs": []})
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
files = []
|
||||||
|
for filename in sorted(os.listdir(LOG_DIR), reverse=True):
|
||||||
|
if filename.endswith('.csv'):
|
||||||
|
filepath = os.path.join(LOG_DIR, filename)
|
||||||
|
stat = os.stat(filepath)
|
||||||
|
|
||||||
|
# Check if CSV is valid
|
||||||
|
if self.is_valid_csv(filepath):
|
||||||
|
files.append({
|
||||||
|
"name": filename,
|
||||||
|
"size": self.format_file_size(stat.st_size),
|
||||||
|
"date": datetime.fromtimestamp(stat.st_mtime).strftime('%Y-%m-%d %H:%M:%S'),
|
||||||
|
"path": filename,
|
||||||
|
"valid": True
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
files.append({
|
||||||
|
"name": filename,
|
||||||
|
"size": self.format_file_size(stat.st_size),
|
||||||
|
"date": datetime.fromtimestamp(stat.st_mtime).strftime('%Y-%m-%d %H:%M:%S'),
|
||||||
|
"path": filename,
|
||||||
|
"valid": False,
|
||||||
|
"error": "Invalid CSV format"
|
||||||
|
})
|
||||||
|
|
||||||
|
self.send_json_response({"logs": files})
|
||||||
|
except Exception as e:
|
||||||
|
self.send_json_response({"error": str(e), "logs": []})
|
||||||
|
|
||||||
|
def handle_log_file_request(self):
|
||||||
|
"""Return contents of a specific log file as JSON"""
|
||||||
|
# Extract filename from path
|
||||||
|
parts = self.path.split('/')
|
||||||
|
if len(parts) < 4:
|
||||||
|
self.send_error(400, "Invalid log file request")
|
||||||
|
return
|
||||||
|
|
||||||
|
filename = parts[3]
|
||||||
|
filepath = os.path.join(LOG_DIR, filename)
|
||||||
|
|
||||||
|
if not os.path.exists(filepath):
|
||||||
|
self.send_error(404, "Log file not found")
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
if filename.endswith('.csv'):
|
||||||
|
data = self.csv_to_json(filepath)
|
||||||
|
if data is None:
|
||||||
|
self.send_json_response({
|
||||||
|
"error": "Failed to parse CSV file",
|
||||||
|
"filename": filename,
|
||||||
|
"valid": False
|
||||||
|
})
|
||||||
|
return
|
||||||
|
|
||||||
|
self.send_json_response({
|
||||||
|
"data": data,
|
||||||
|
"filename": filename,
|
||||||
|
"valid": True
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
self.send_error(400, "Unsupported file format")
|
||||||
|
except Exception as e:
|
||||||
|
self.send_error(500, f"Error reading log file: {str(e)}")
|
||||||
|
|
||||||
|
def csv_to_json(self, filepath):
|
||||||
|
"""Convert CSV file to JSON array"""
|
||||||
|
try:
|
||||||
|
data = []
|
||||||
|
with open(filepath, 'r') as f:
|
||||||
|
reader = csv.DictReader(f)
|
||||||
|
for row in reader:
|
||||||
|
data.append({
|
||||||
|
"click": int(row["click_number"]),
|
||||||
|
"delay_ms": int(row["delay_ms"]),
|
||||||
|
"timestamp": int(row["timestamp"])
|
||||||
|
})
|
||||||
|
return data
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error parsing CSV {filepath}: {str(e)}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def is_valid_csv(self, filepath):
|
||||||
|
"""Check if a file contains valid CSV"""
|
||||||
|
try:
|
||||||
|
with open(filepath, 'r') as f:
|
||||||
|
reader = csv.DictReader(f)
|
||||||
|
# Try to read first row
|
||||||
|
next(reader)
|
||||||
|
return True
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def send_json_response(self, data):
|
||||||
|
"""Send JSON response with proper headers"""
|
||||||
|
response = json.dumps(data, indent=2)
|
||||||
|
self.send_response(200)
|
||||||
|
self.send_header('Content-type', 'application/json')
|
||||||
|
self.send_header('Access-Control-Allow-Origin', '*')
|
||||||
|
self.send_header('Content-Length', str(len(response)))
|
||||||
|
self.end_headers()
|
||||||
|
self.wfile.write(response.encode())
|
||||||
|
|
||||||
|
def format_file_size(self, size_bytes):
|
||||||
|
"""Format file size in human-readable format"""
|
||||||
|
for unit in ['B', 'KB', 'MB', 'GB']:
|
||||||
|
if size_bytes < 1024.0:
|
||||||
|
return f"{size_bytes:.1f} {unit}"
|
||||||
|
size_bytes /= 1024.0
|
||||||
|
return f"{size_bytes:.1f} TB"
|
||||||
|
|
||||||
|
def run_server():
|
||||||
|
"""Start the web server"""
|
||||||
|
print(f"Starting autoclicker visualization server on port {PORT}")
|
||||||
|
print(f"Log directory: {LOG_DIR}")
|
||||||
|
print("Open your browser to: http://localhost:8661")
|
||||||
|
print("Press Ctrl+C to stop the server")
|
||||||
|
|
||||||
|
try:
|
||||||
|
with socketserver.TCPServer(("", PORT), ClickServerHandler) as httpd:
|
||||||
|
httpd.serve_forever()
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print("\nServer stopped")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Server error: {str(e)}")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
run_server()
|
||||||
71
scripts/osrs/autoclicker/visualize-clicks.sh
Executable file
71
scripts/osrs/autoclicker/visualize-clicks.sh
Executable file
@@ -0,0 +1,71 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Script to visualize autoclicker log files
|
||||||
|
# Starts Python server and opens the HTML visualization tool
|
||||||
|
|
||||||
|
VISUALIZER_FILE="click-visualizer.html"
|
||||||
|
LOG_DIR="/tmp/autoclicker_logs"
|
||||||
|
SERVER_SCRIPT="click_server.py"
|
||||||
|
SERVER_PORT=8661
|
||||||
|
|
||||||
|
# Check if visualization file exists
|
||||||
|
if [ ! -f "$VISUALIZER_FILE" ]; then
|
||||||
|
echo "Error: Visualization tool not found at $VISUALIZER_FILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if server script exists
|
||||||
|
if [ ! -f "$SERVER_SCRIPT" ]; then
|
||||||
|
echo "Error: Server script not found at $SERVER_SCRIPT"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if Python is available
|
||||||
|
if ! command -v python3 &> /dev/null; then
|
||||||
|
echo "Error: Python 3 is not installed. Install it with: sudo pacman -S python"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if we have any log files
|
||||||
|
if [ ! -d "$LOG_DIR" ] || [ -z "$(ls -A "$LOG_DIR")" ]; then
|
||||||
|
echo "No autoclicker log files found in $LOG_DIR"
|
||||||
|
echo "Run the enhanced autoclicker first to generate data."
|
||||||
|
echo ""
|
||||||
|
echo "Starting server anyway (you can generate logs while it's running)..."
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Starting autoclicker visualization server..."
|
||||||
|
echo "Server will be available at: http://localhost:$SERVER_PORT"
|
||||||
|
echo "Log directory: $LOG_DIR"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Start the Python server in the background
|
||||||
|
python3 "$SERVER_SCRIPT" &
|
||||||
|
SERVER_PID=$!
|
||||||
|
|
||||||
|
# Give the server a moment to start
|
||||||
|
sleep 2
|
||||||
|
|
||||||
|
# Check if server started successfully
|
||||||
|
if ! ps -p $SERVER_PID > /dev/null; then
|
||||||
|
echo "Error: Failed to start server"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Open browser
|
||||||
|
if command -v xdg-open &> /dev/null; then
|
||||||
|
xdg-open "http://localhost:$SERVER_PORT"
|
||||||
|
elif command -v open &> /dev/null; then
|
||||||
|
open "http://localhost:$SERVER_PORT"
|
||||||
|
else
|
||||||
|
echo "Server started successfully!"
|
||||||
|
echo "Open your browser and navigate to: http://localhost:$SERVER_PORT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Server is running in the background (PID: $SERVER_PID)"
|
||||||
|
echo "Press Ctrl+C to stop the server when you're done"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Wait for server to finish (it will run until manually stopped)
|
||||||
|
wait $SERVER_PID
|
||||||
@@ -24,7 +24,7 @@ RANDOM_DELAY_LEFT=0.05
|
|||||||
#RANDOM_DELAY_LEFT=0.3
|
#RANDOM_DELAY_LEFT=0.3
|
||||||
|
|
||||||
### PRAYER BONES
|
### PRAYER BONES
|
||||||
MOVE_DISTANCE=90
|
MOVE_DISTANCE=120
|
||||||
#RANDOM_NUM=$((RANDOM % 101)) # Generate 0-100
|
#RANDOM_NUM=$((RANDOM % 101)) # Generate 0-100
|
||||||
#RANDOM_DELAY=$(echo "scale=3; 0.5 + $RANDOM_NUM / 1000" | bc)
|
#RANDOM_DELAY=$(echo "scale=3; 0.5 + $RANDOM_NUM / 1000" | bc)
|
||||||
RANDOM_DELAY=0.100
|
RANDOM_DELAY=0.100
|
||||||
3
scripts/osrs/osrs-click.sh
Executable file
3
scripts/osrs/osrs-click.sh
Executable file
@@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
ydotool click 0xC0 # Left click
|
||||||
93
scripts/osrs/osrs-drop.sh
Executable file
93
scripts/osrs/osrs-drop.sh
Executable file
@@ -0,0 +1,93 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Mouse toggle script for Sway
|
||||||
|
# Toggles mouse position 60 (MOVE_DISTANCE) pixels upwards on each execution
|
||||||
|
# Requires ydotool and ydotoold daemon running
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
|
||||||
|
MOVE_DISTANCE=70
|
||||||
|
BOTTOM_MARGIN=190
|
||||||
|
|
||||||
|
RANDOM_DELAY_MIN=0
|
||||||
|
RANDOM_DELAY_MAX=0.25
|
||||||
|
RANDOM_DELAY=$(awk -v min=$RANDOM_DELAY_MIN -v max=$RANDOM_DELAY_MAX 'BEGIN { srand(); printf "%.2f\n", min + rand() * (max - min) }')
|
||||||
|
#WL_FIND_CURSOR_BIN="${WL_FIND_CURSOR_BIN:-wl-find-cursor}"
|
||||||
|
WL_FIND_CURSOR_BIN="/home/raga/repos/linux/wl-find-cursor/wl-find-cursor"
|
||||||
|
|
||||||
|
ENABLED_FILE="/tmp/osrs_drop__enabled"
|
||||||
|
LOCK_FILE="/tmp/osrs_drop__lock"
|
||||||
|
|
||||||
|
# Verify dependencies
|
||||||
|
if ! command -v ydotool &> /dev/null; then
|
||||||
|
echo "Error: ydotool is not installed. Install it with: sudo pacman -S ydotool"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if ! command -v bc &> /dev/null; then
|
||||||
|
echo "Error: bc is not installed. Install it with: sudo pacman -S bc"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if ! command -v jq &> /dev/null; then
|
||||||
|
echo "Error: jq is not installed. Install it with: sudo pacman -S jq"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if ! command -v "$WL_FIND_CURSOR_BIN" &> /dev/null; then
|
||||||
|
echo "Error: wl-find-cursor is not installed or not in PATH (looked for '$WL_FIND_CURSOR_BIN')."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Verify lock file
|
||||||
|
if [ -f "$LOCK_FILE" ]; then
|
||||||
|
echo "Script is already running, skipping..."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
echo $$ > "$LOCK_FILE"
|
||||||
|
trap 'rm -f "$LOCK_FILE"' EXIT
|
||||||
|
|
||||||
|
# Check if script should toggle on/off or execute
|
||||||
|
if [ "$1" = "toggle" ]; then
|
||||||
|
if [ -f "$ENABLED_FILE" ]; then
|
||||||
|
rm "$ENABLED_FILE"
|
||||||
|
echo "Mouse toggle script DISABLED"
|
||||||
|
else
|
||||||
|
echo "enabled" > "$ENABLED_FILE"
|
||||||
|
echo "Mouse toggle script ENABLED"
|
||||||
|
fi
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Verify script is enabled
|
||||||
|
if [ ! -f "$ENABLED_FILE" ]; then
|
||||||
|
echo "Mouse toggle script is DISABLED. Use '$0 toggle' to enable."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Verify ydotoold daemon is running
|
||||||
|
if ! pgrep -x "ydotoold" > /dev/null; then
|
||||||
|
echo "Starting ydotoold daemon..."
|
||||||
|
sudo ydotoold &
|
||||||
|
sleep 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
CURSOR_POS=$("$WL_FIND_CURSOR_BIN" -p)
|
||||||
|
if [ -z "$CURSOR_POS" ]; then
|
||||||
|
echo "Error: Unable to determine cursor position."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
read -r CURSOR_X CURSOR_Y <<< "$CURSOR_POS"
|
||||||
|
|
||||||
|
BOTTOM_LIMIT=$(swaymsg -r -t get_outputs | jq --argjson cx "$CURSOR_X" --argjson cy "$CURSOR_Y" --argjson margin "$BOTTOM_MARGIN" '
|
||||||
|
.[] | select(.active == true) |
|
||||||
|
select($cx >= .rect.x and $cx < (.rect.x + .rect.width) and
|
||||||
|
$cy >= .rect.y and $cy < (.rect.y + .rect.height)) |
|
||||||
|
(.rect.y + .rect.height - $margin)
|
||||||
|
' | head -n 1)
|
||||||
|
|
||||||
|
if [ -n "$BOTTOM_LIMIT" ]; then
|
||||||
|
if [ "$(printf "%.0f" "$CURSOR_Y")" -ge "$(printf "%.0f" "$BOTTOM_LIMIT")" ]; then
|
||||||
|
echo "Cursor is already within ${BOTTOM_MARGIN}px of the bottom, skipping move."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
ydotool mousemove -- 0 $MOVE_DISTANCE
|
||||||
1367
testing/wttrin-json-output-Tallinn?format=j1
Normal file
1367
testing/wttrin-json-output-Tallinn?format=j1
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user