scwrypts v3 refactor
This commit is contained in:
4
scwrypts/.config/env.template
Normal file
4
scwrypts/.config/env.template
Normal file
@ -0,0 +1,4 @@
|
||||
#!/bin/zsh
|
||||
export DESKTOP__SFX_PATH=
|
||||
export DESKTOP__WALLPAPER_PATH=
|
||||
export WRYN__SERVER_HOSTNAMES=
|
4
scwrypts/.config/env.template.descriptions
Normal file
4
scwrypts/.config/env.template.descriptions
Normal file
@ -0,0 +1,4 @@
|
||||
DESKTOP__SFX_PATH | directory containing sound effects
|
||||
DESKTOP__DESKTOP_PATH | directory containing desktop background images
|
||||
|
||||
WRYN__SERVER_HOSTNAMES | home server data
|
73
scwrypts/desktop/backlight
Executable file
73
scwrypts/desktop/backlight
Executable file
@ -0,0 +1,73 @@
|
||||
#!/bin/zsh
|
||||
DEPENDENCIES+=()
|
||||
REQUIRED_ENV+=()
|
||||
|
||||
use desktop/notify --group dotwryn
|
||||
|
||||
CHECK_ENVIRONMENT
|
||||
#####################################################################
|
||||
|
||||
{
|
||||
command -v xbacklight && UTIL=xbacklight
|
||||
command -v gmux_backlight && UTIL=gmux_backlight
|
||||
command -v enlighten && UTIL=enlighten
|
||||
} >/dev/null 2>&1
|
||||
|
||||
[[ $UTIL =~ ^enlighten$ ]] && {
|
||||
CURRENT_PERCENT=$(enlighten | sed 's/.*(//;s/%.*//')
|
||||
[[ $CURRENT_PERCENT -gt 60 ]] && DELTA=20
|
||||
[[ $CURRENT_PERCENT -le 60 ]] && DELTA=10
|
||||
[[ $CURRENT_PERCENT -le 40 ]] && DELTA=5
|
||||
[[ $CURRENT_PERCENT -le 10 ]] && DELTA=1
|
||||
}
|
||||
|
||||
case $1 in
|
||||
up )
|
||||
case $UTIL in
|
||||
xbacklight ) xbacklight + 10 ;;
|
||||
gmux_backlight ) gmux_backlight +100 ;;
|
||||
|
||||
enlighten )
|
||||
[[ $CURRENT_PERCENT -ge 99 ]] && NOTIFY_SEND 'at maximum brightness' && exit 0
|
||||
enlighten +${DELTA}%
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
down )
|
||||
case $UTIL in
|
||||
xbacklight ) xbacklight - 10 ;;
|
||||
gmux_backlight ) gmux_backlight -100 ;;
|
||||
|
||||
enlighten )
|
||||
[[ $CURRENT_PERCENT -le 1 ]] && NOTIFY_SEND 'at minimum brightness' && exit 0
|
||||
[[ $CURRENT_PERCENT -le 2 ]] && ARGS='=1%' || ARGS="-${DELTA}%"
|
||||
enlighten "$ARGS"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
set )
|
||||
[ ! $2 ] && FAIL 1 'no value provided to set'
|
||||
case $UTIL in
|
||||
xbacklight ) xbacklight -set $2 ;;
|
||||
gmux_backlight ) gmux_backlight $2 ;;
|
||||
enlighten ) enlighten "=$2" ;;
|
||||
esac
|
||||
;;
|
||||
min | minimum )
|
||||
case $UTIL in
|
||||
enlighten ) enlighten '=1%' ;;
|
||||
esac
|
||||
;;
|
||||
max | maximum )
|
||||
case $UTIL in
|
||||
enlighten ) enlighten '=100%' ;;
|
||||
esac
|
||||
;;
|
||||
query | '' )
|
||||
case $UTIL in
|
||||
enlighten ) NOTIFY_SUCCESS "current brightness : $(enlighten)" ;;
|
||||
esac
|
||||
;;
|
||||
|
||||
* ) NOTIFY_FAIL 1 "operation '$1' not supported" ;;
|
||||
esac
|
10
scwrypts/desktop/get-colorscheme-hex
Executable file
10
scwrypts/desktop/get-colorscheme-hex
Executable file
@ -0,0 +1,10 @@
|
||||
#!/bin/zsh
|
||||
DEPENDENCIES+=()
|
||||
REQUIRED_ENV+=()
|
||||
|
||||
use desktop/colorscheme --group dotwryn
|
||||
|
||||
CHECK_ENVIRONMENT
|
||||
#####################################################################
|
||||
|
||||
GET_COLORSCHEME_HEX $@
|
40
scwrypts/desktop/i3/lock
Executable file
40
scwrypts/desktop/i3/lock
Executable file
@ -0,0 +1,40 @@
|
||||
#!/bin/zsh
|
||||
DEPENDENCIES+=(
|
||||
i3lock
|
||||
)
|
||||
REQUIRED_ENV+=()
|
||||
|
||||
use desktop/colorscheme --group dotwryn
|
||||
use desktop/notify --group dotwryn
|
||||
|
||||
CHECK_ENVIRONMENT
|
||||
#####################################################################
|
||||
|
||||
ARGS=(
|
||||
--ignore-empty-password
|
||||
--force-clock
|
||||
--pass-screen-keys
|
||||
--pass-media-keys
|
||||
--pass-volume-keys
|
||||
--pass-power-keys
|
||||
--verif-text=''
|
||||
--wrong-text=''
|
||||
--blur=11
|
||||
--insidever-color=$(GET_COLORSCHEME_HEX 6)
|
||||
--ringver-color=$(GET_COLORSCHEME_HEX 10)
|
||||
--insidewrong-color=$(GET_COLORSCHEME_HEX 1)
|
||||
--ringwrong-color=$(GET_COLORSCHEME_HEX 9)
|
||||
--inside-color=$(GET_COLORSCHEME_HEX 0)
|
||||
--ring-color=$(GET_COLORSCHEME_HEX 2)
|
||||
--time-color=$(GET_COLORSCHEME_HEX 7)
|
||||
--date-color=$(GET_COLORSCHEME_HEX 15)
|
||||
--keyhl-color=$(GET_COLORSCHEME_HEX 11)
|
||||
--bshl-color=$(GET_COLORSCHEME_HEX 13)
|
||||
)
|
||||
|
||||
RADIUS=$(xrandr | grep 'connected primary' | sed 's/.* \([0-9]\+\)x.*/\1/' | awk '{print int($1*0.08)}')
|
||||
[ $RADIUS ] && ARGS+=(--radius=$RADIUS)
|
||||
|
||||
i3lock ${ARGS[@]} \
|
||||
|| NOTIFY_ERROR 'i3lock-color' 'something went wrong; unable to lock' \
|
||||
;
|
16
scwrypts/desktop/i3/logout
Executable file
16
scwrypts/desktop/i3/logout
Executable file
@ -0,0 +1,16 @@
|
||||
#!/bin/zsh
|
||||
DEPENDENCIES+=(
|
||||
i3-nagbar
|
||||
)
|
||||
REQUIRED_ENV+=()
|
||||
|
||||
use desktop/notify --group dotwryn
|
||||
|
||||
CHECK_ENVIRONMENT
|
||||
#####################################################################
|
||||
i3-nagbar \
|
||||
-t warning \
|
||||
-m 'Do you really want to exit i3?' \
|
||||
-B 'Yes' "notify-send 'system' 'exiting i3...' -i face-tired; i3-msg exit" \
|
||||
|| NOTIFY_ERROR 'unable to launch i3-nagbar'
|
||||
|
27
scwrypts/desktop/i3/set-background
Executable file
27
scwrypts/desktop/i3/set-background
Executable file
@ -0,0 +1,27 @@
|
||||
#!/bin/zsh
|
||||
DEPENDENCIES+=()
|
||||
REQUIRED_ENV+=(
|
||||
DESKTOP__WALLPAPER_PATH
|
||||
)
|
||||
|
||||
CHECK_ENVIRONMENT
|
||||
#####################################################################
|
||||
|
||||
|
||||
[ ! -d $WALLPAPER_PATH ] \
|
||||
&& FAIL 1 "no such directory for DESKTOP__WALLPAPER_PATH='$DESKTOP__WALLPAPER_PATH'"
|
||||
|
||||
SELECTION="$1"
|
||||
[ ! $SELECTION ] && SELECTION=random
|
||||
|
||||
case $SELECTION in
|
||||
random )
|
||||
feh --recursive --randomize --bg-fill $WALLPAPER_PATH
|
||||
;;
|
||||
* )
|
||||
[ ! -f $DESKTOP__WALLPAPER_PATH/$SELECTION ] \
|
||||
&& FAIL 2 "no such wallpaper '$SELECTION' in wallpaper path"
|
||||
|
||||
feh --bg-fill $DESKTOP__WALLPAPER_PATH/$SELECTION
|
||||
;;
|
||||
esac
|
14
scwrypts/desktop/kitty-alternate-theme
Executable file
14
scwrypts/desktop/kitty-alternate-theme
Executable file
@ -0,0 +1,14 @@
|
||||
#!/bin/zsh
|
||||
DEPENDENCIES+=()
|
||||
REQUIRED_ENV+=()
|
||||
|
||||
use desktop/colorscheme --group dotwryn
|
||||
|
||||
CHECK_ENVIRONMENT
|
||||
#####################################################################
|
||||
SET_THEME alternate
|
||||
i3-sensible-terminal &
|
||||
PID=$!
|
||||
sleep 0.1
|
||||
SET_THEME main
|
||||
wait $!
|
10
scwrypts/desktop/play-sound
Executable file
10
scwrypts/desktop/play-sound
Executable file
@ -0,0 +1,10 @@
|
||||
#!/bin/zsh
|
||||
DEPENDENCIES+=()
|
||||
REQUIRED_ENV+=()
|
||||
|
||||
use media/audio --group dotwryn
|
||||
|
||||
CHECK_ENVIRONMENT
|
||||
#####################################################################
|
||||
|
||||
MEDIA__PLAY_SFX $@
|
46
scwrypts/desktop/pulseaudio
Executable file
46
scwrypts/desktop/pulseaudio
Executable file
@ -0,0 +1,46 @@
|
||||
#!/bin/zsh
|
||||
source $HOME/.config/wryn/env.zsh
|
||||
DEPENDENCIES+=(
|
||||
pactl
|
||||
)
|
||||
REQUIRED_ENV+=()
|
||||
|
||||
use desktop/notify --group dotwryn
|
||||
use media/audio --group dotwryn
|
||||
|
||||
#####################################################################
|
||||
|
||||
DEVICE="$1"
|
||||
COMMAND="$2"
|
||||
|
||||
case $DEVICE in
|
||||
sink ) AMIXER_DEVICE=Master ;;
|
||||
source ) AMIXER_DEVICE=Capture ;;
|
||||
* ) NOTIFY_FAIL 1 "Unsupported device '$DEVICE'" ;;
|
||||
esac
|
||||
|
||||
DEFAULT_DEVICE="@DEFAULT_$(echo $DEVICE | tr '[:lower:]' '[:upper:]')@"
|
||||
case $COMMAND in
|
||||
up )
|
||||
pactl set-$DEVICE-volume $DEFAULT_DEVICE +10% \
|
||||
|| NOTIFY_ERROR "pactl error with set-$DEVICE-volume"
|
||||
|
||||
MEDIA__PLAY_SFX volume
|
||||
;;
|
||||
|
||||
down )
|
||||
pactl set-$DEVICE-volume $DEFAULT_DEVICE -10% \
|
||||
|| NOTIFY_ERROR "pactl error with set-$DEVICE-volume"
|
||||
|
||||
MEDIA__PLAY_SFX volume
|
||||
;;
|
||||
|
||||
mute )
|
||||
pactl set-$DEVICE-mute $DEFAULT_DEVICE toggle \
|
||||
&& NOTIFY_SUCCESS "default $DEVICE" "$(amixer sget $AMIXER_DEVICE | grep -q '\[on\]' && echo unmuted || echo muted)" \
|
||||
|| NOTIFY_ERROR "pactl error with set-$DEVICE-mute"
|
||||
MEDIA__PLAY_SFX mute
|
||||
;;
|
||||
|
||||
* ) NOTIFY_FAIL 1 "Unsupported command '$COMMAND'" ;;
|
||||
esac
|
52
scwrypts/desktop/screen-blank
Executable file
52
scwrypts/desktop/screen-blank
Executable file
@ -0,0 +1,52 @@
|
||||
#!/bin/zsh
|
||||
DEPENDENCIES+=(xset)
|
||||
REQUIRED_ENV+=()
|
||||
|
||||
use desktop/notify --group dotwryn
|
||||
|
||||
CHECK_ENVIRONMENT
|
||||
#####################################################################
|
||||
|
||||
case $1 in
|
||||
enable | disable | query | toggle ) ACTION="$1" ;;
|
||||
* )
|
||||
[ ! $1 ] && ACTION=toggle
|
||||
echo $ACTION
|
||||
;;
|
||||
esac
|
||||
|
||||
[[ $ACTION =~ ^toggle$ ]] && {
|
||||
xset -q | grep -qi 'prefer blanking: *no' \
|
||||
&& ACTION='enable' || ACTION='disable'
|
||||
}
|
||||
|
||||
[ ! $ACTION ] && NOTIFY_FAIL 1 "unknown screen blank action '$1'"
|
||||
|
||||
case $ACTION in
|
||||
enable ) : \
|
||||
&& STATUS 'enabling screen blank' \
|
||||
&& xset +dpms \
|
||||
&& xset s blank \
|
||||
&& xset s on \
|
||||
&& NOTIFY_SUCCESS 'enabled screen blank' \
|
||||
|| NOTIFY_FAIL 2 'error enabling screen blank'
|
||||
;;
|
||||
|
||||
disable ) : \
|
||||
&& STATUS 'disabling screen blank' \
|
||||
&& xset dpms 0 0 0 \
|
||||
&& xset s noblank \
|
||||
&& xset s off \
|
||||
&& NOTIFY_SUCCESS 'disabled screen blank' \
|
||||
|| NOTIFY_FAIL 2 'error disabling screen blank'
|
||||
;;
|
||||
|
||||
query )
|
||||
xset -q | grep -qi 'prefer blanking: *no' \
|
||||
&& CURRENT_STATE='disabled' || CURRENT_STATE='enabled'
|
||||
|
||||
[ ! $CURRENT_STATE ] && NOTIFY_FAIL 3 'unable to determine current setting'
|
||||
|
||||
NOTIFY_SUCCESS "screen blank is currently \\033[0;34m$CURRENT_STATE"
|
||||
;;
|
||||
esac
|
7
scwrypts/dotwryn.scwrypts.zsh
Normal file
7
scwrypts/dotwryn.scwrypts.zsh
Normal file
@ -0,0 +1,7 @@
|
||||
SCWRYPTS_GROUPS+=(dotwryn)
|
||||
|
||||
export SCWRYPTS_TYPE__dotwryn=zsh
|
||||
export SCWRYPTS_ROOT__dotwryn="$DOTWRYN/scwrypts"
|
||||
export SCWRYPTS_COLOR__dotwryn='\033[0;31m'
|
||||
|
||||
[ $DOTWRYN ] || source "$HOME/.config/wryn/env.zsh"
|
97
scwrypts/home/update-all-servers
Executable file
97
scwrypts/home/update-all-servers
Executable file
@ -0,0 +1,97 @@
|
||||
#!/bin/zsh
|
||||
DEPENDENCIES+=(
|
||||
hostnamectl
|
||||
)
|
||||
REQUIRED_ENV+=(
|
||||
WRYN__SERVER_HOSTNAMES
|
||||
)
|
||||
|
||||
CHECK_ENVIRONMENT
|
||||
#####################################################################
|
||||
|
||||
SESSION='update'
|
||||
LOCAL_HOST="$(hostnamectl --static)"
|
||||
|
||||
UPDATE_REMINDER="{ echo \\UPDATE : an error occured - you may want to stop execution of 'update-all-servers' on $LOCAL_HOST\\\"; read; }"
|
||||
|
||||
CHECK_SESSION() {
|
||||
tmux list-sessions >/dev/null 2>&1 \
|
||||
| grep -q "^$SESSION" && return 0 || return 1
|
||||
}
|
||||
|
||||
UPDATE_ALL() {
|
||||
STATUS "starting '$@'"
|
||||
for SERVER in ${WRYN__SERVER_HOSTNAMES[@]}; do UPDATE $SERVER "$@"; done
|
||||
WAIT_FOR_UPDATES \
|
||||
&& SUCCESS "'$@' finished across all servers" \
|
||||
|| FAIL 69 'user abort' \
|
||||
;
|
||||
}
|
||||
|
||||
UPDATE() {
|
||||
local SERVER_HOST="$1"
|
||||
local COMMAND="${@:2} || $UPDATE_REMINDER"
|
||||
[[ $2 =~ ^reboot ]] && [[ $SERVER_HOST =~ $LOCAL_HOST ]] && return 0
|
||||
|
||||
[[ $SERVER_HOST =~ $LOCAL_HOST ]] || {
|
||||
COMMAND="ssh -t $SERVER_HOST.local 'source ~/.zshrc >/dev/null 2>&1; $COMMAND'"
|
||||
}
|
||||
|
||||
tmux new-window -t $SESSION -n $SERVER_HOST "source ~/.zshrc >/dev/null 2>&1; $COMMAND"
|
||||
}
|
||||
|
||||
WAIT_FOR_UPDATES() {
|
||||
while [[ $(tmux list-windows -t $SESSION 2>/dev/null | wc -l) -gt 1 ]]
|
||||
do
|
||||
sleep 1
|
||||
done
|
||||
|
||||
CHECK_SESSION
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
|
||||
|
||||
CURRENT_SESSION=$(\
|
||||
tmux list-panes -a -F '#{pane_tty} #{session_name}' \
|
||||
| grep $(tty) \
|
||||
| awk '{print $2;}' \
|
||||
)
|
||||
|
||||
#####################################################################
|
||||
|
||||
CHECK_SESSION && FAIL 1 'update currently in progress'
|
||||
|
||||
tmux new -d -s $SESSION "echo 'updating all systems'; echo '(leave this window open)'; while true; do sleep 30; done"
|
||||
|
||||
yN 'after update, do you want to reboot all machines?' && REBOOT=1 || REBOOT=0
|
||||
REMINDER
|
||||
REMINDER 'manual action is required; (in another tab) connect to tmux:'
|
||||
REMINDER "tmux a -t $SESSION"
|
||||
REMINDER
|
||||
REMINDER 'to stop the update at any time, run:'
|
||||
REMINDER "tmux kill-session -t $SESSION"
|
||||
REMINDER
|
||||
|
||||
[ $CURRENT_SESSION ] && {
|
||||
SUCCESS 'currently in a tmux session; opening new window...'
|
||||
tmux new-window -t $CURRENT_SESSION "unset TMUX; tmux a -t $SESSION"
|
||||
}
|
||||
|
||||
UPDATE_ALL 'yay -Syu'
|
||||
UPDATE_ALL 'cd ~/.wryn; git pull --autostash'
|
||||
UPDATE_ALL '~/.wryn/bin/scwrypts config update'
|
||||
UPDATE_ALL '~/.wryn/bin/scwrypts media push'
|
||||
UPDATE_ALL '~/.wryn/bin/scwrypts media pull'
|
||||
UPDATE_ALL 'command -v i3-msg >/dev/null 2>&1 || exit 0; ~/.wryn/bin/scwrypts i3 font override'
|
||||
|
||||
[[ $REBOOT -eq 1 ]] && UPDATE_ALL 'reboot || sudo reboot'
|
||||
|
||||
tmux kill-session -t $SESSION >/dev/null 2>&1
|
||||
CHECK_SESSION && WARNING "unable to close tmux session '$SESSION'"
|
||||
|
||||
SUCCESS
|
||||
SUCCESS 'finished system update accross all servers'
|
||||
SUCCESS
|
||||
|
||||
[[ $REBOOT -eq 1 ]] && { STATUS 'rebooting host machine'; sleep 3; reboot || sudo reboot; }
|
27
scwrypts/lib/desktop/colorscheme.module.zsh
Normal file
27
scwrypts/lib/desktop/colorscheme.module.zsh
Normal file
@ -0,0 +1,27 @@
|
||||
#####################################################################
|
||||
|
||||
DEPENDENCIES+=(
|
||||
awk sed tr
|
||||
)
|
||||
REQUIRED_ENV+=()
|
||||
|
||||
#####################################################################
|
||||
|
||||
GET_COLORSCHEME_HEX() {
|
||||
[ $1 ] && [[ $1 -le 15 ]] && [[ $1 -ge 0 ]] \
|
||||
|| FAIL 1 'must provide ANSI color number 0-15'
|
||||
|
||||
grep "^color$1 " "$DOTWRYN/colorschemes/kitty.main" \
|
||||
| awk '{print $2}' \
|
||||
| sed 's/ //g; s/#//g' \
|
||||
| tr '[:lower:]' '[:upper:]' \
|
||||
;
|
||||
}
|
||||
|
||||
SET_THEME() {
|
||||
local THEME="$DOTWRYN/colorschemes/kitty.$1"
|
||||
[ ! -f "$THEME" ] && FAIL 1 "no such theme '$1'"
|
||||
local LOCAL_THEME="$HOME/.config/kitty/theme.conf"
|
||||
rm -- $LOCAL_THEME
|
||||
ln -s "$THEME" "$LOCAL_THEME"
|
||||
}
|
19
scwrypts/lib/desktop/notify.module.zsh
Normal file
19
scwrypts/lib/desktop/notify.module.zsh
Normal file
@ -0,0 +1,19 @@
|
||||
#####################################################################
|
||||
|
||||
DEPENDENCIES+=(
|
||||
notify-send
|
||||
)
|
||||
REQUIRED_ENV+=()
|
||||
|
||||
#####################################################################
|
||||
|
||||
NOTIFY_SEND() { notify-send "$SCWRYPT_GROUP : $SCWRYPT_NAME" "$1"; }
|
||||
|
||||
_NOTIFY() {
|
||||
NOTIFY_SEND "$1 : ${*:2}"
|
||||
$1 ${@:2}
|
||||
}
|
||||
|
||||
NOTIFY_SUCCESS() { _NOTIFY SUCCESS $@; }
|
||||
NOTIFY_ERROR() { _NOTIFY ERROR $@; }
|
||||
NOTIFY_FAIL() { _NOTIFY FAIL $@; }
|
38
scwrypts/lib/media/audio.module.zsh
Normal file
38
scwrypts/lib/media/audio.module.zsh
Normal file
@ -0,0 +1,38 @@
|
||||
#####################################################################
|
||||
|
||||
DEPENDENCIES+=(
|
||||
canberra-gtk-play
|
||||
)
|
||||
REQUIRED_ENV+=()
|
||||
|
||||
use desktop/notify --group dotwryn
|
||||
|
||||
#####################################################################
|
||||
|
||||
MEDIA__PLAY_SFX() {
|
||||
local SFX_FILE
|
||||
case $1 in
|
||||
volume ) SFX_FILE=$DESKTOP__SFX_PATH/yaru-message.oga ;;
|
||||
mute ) SFX_FILE=$DESKTOP__SFX_PATH/smooth-dialog-warning.oga ;;
|
||||
backlight ) SFX_FILE=$DESKTOP__SFX_PATH/yaru-audio-volume-change.oga ;;
|
||||
login ) SFX_FILE=$DESKTOP__SFX_PATH/yaru-desktop-login.oga ;;
|
||||
logout ) SFX_FILE=$DESKTOP__SFX_PATH/smooth-desktop-login.oga ;;
|
||||
notify ) SFX_FILE=$DESKTOP__SFX_PATH/yaru-complete.oga ;;
|
||||
undock ) SFX_FILE=$DESKTOP__SFX_PATH/yaru-desktop-login.oga ;;
|
||||
homedock ) SFX_FILE=$DESKTOP__SFX_PATH/homedock.oga ;;
|
||||
gamedock ) SFX_FILE=$DESKTOP__SFX_PATH/gamedock.oga ;;
|
||||
|
||||
* ) SFX_FILE="$1"
|
||||
;;
|
||||
esac
|
||||
|
||||
[ -f $SFX_FILE ] \
|
||||
&& STATUS "detected file '$SFX_FILE'" \
|
||||
|| NOTIFY_FAIL 1 "unable to locate sfx file '$1'" \
|
||||
;
|
||||
|
||||
STATUS 'starting playback'
|
||||
canberra-gtk-play -f "$SFX_FILE" \
|
||||
&& SUCCESS "finished output of '$SFX_FILE'" \
|
||||
|| NOTIFY_FAIL 1 "something went wrong playing file '$SFX_FILE'"
|
||||
}
|
Reference in New Issue
Block a user