minor updates

This commit is contained in:
Arthur Khachaturov 2024-09-19 04:25:07 +03:00
parent e3790a4f3f
commit 628baf3eea
No known key found for this signature in database
GPG key ID: CAC2B7EB6DF45D55
32 changed files with 655 additions and 123 deletions

View file

@ -1,8 +1,18 @@
systemctl --user import-environment DISPLAY
export TERMINAL=/usr/bin/alacritty
export TERM=/usr/bin/alacritty
export _JAVA_AWT_WM_NONREPARENTING=1
export AWT_TOOLKIT=MToolkit
set -a
TERMINAL=/usr/bin/alacritty
TERM=/usr/bin/alacritty
_JAVA_AWT_WM_NONREPARENTING=1
AWT_TOOLKIT=MToolkit
MOZ_USE_XINPUT2=1
XDG_CURRENT_DESKTOP="gtk"
XDG_SESSION_DESKTOP="$XDG_CURRENT_DESKTOP"
WINDOW_MANAGER="dwm"
set +a
# vim: ft=bash

View file

@ -3,15 +3,15 @@
declare -A cases
while read -r element; do
case "$element" in
"#Open"*)
cases["open"]+=$element
;;
"#Mark as read"*)
cases["read"]+=$element
;;
*) cases["$element"]="$element"
esac
case "$element" in
"#Open"*)
cases["open"]+=$element
;;
"#Mark as read"*)
cases["read"]+=$element
;;
*) cases["$element"]="$element"
esac
done

View file

@ -1,15 +1,29 @@
-- Remap leader key to <Space>
vim.g.mapleader = ' '
vim.g.maplocalleader = ' '
vim.keymap.set({ 'n', 'v' }, '<Space>', '<Nop>', { silent = true })
-- Load modules
-- Load basic configuration
require("config")
require("utils.lazy").lazy_init()
-- Init lazy.nvim plugin manager
local lazypath = vim.fn.stdpath('data') .. '/lazy/lazy.nvim'
if not vim.loop.fs_stat(lazypath) then
vim.fn.system {
'git',
'clone',
'--filter=blob:none',
'https://github.com/folke/lazy.nvim.git',
'--branch=stable',
lazypath,
}
end
vim.opt.rtp:prepend(lazypath)
-- Load plugins
require("lazy").setup("plugins", {
change_detection = {
enabled = false,
notify = false,
},
})
-- Load lsp configuration
require("lsp")

View file

@ -1,5 +1,14 @@
-- Set proper tabstop for go
vim.api.nvim_create_autocmd('FileType', {
pattern = "go",
command = "setlocal tabstop=4",
command = "setlocal tabstop=4 noexpandtab",
})
-- Remove trailing whitespaces on save
vim.api.nvim_create_autocmd('BufWritePre', {
callback = function ()
local view = vim.fn.winsaveview()
vim.cmd('%s/\\s\\+$//e')
vim.fn.winrestview(view)
end
})

View file

@ -1,5 +1,10 @@
local map = vim.keymap.set
-- Remap leader to <Space>
vim.g.mapleader = ' '
vim.g.maplocalleader = ' '
map({ 'n', 'v' }, '<Space>', '<Nop>', { silent = true })
-- Unbind keys
map('n', '<C-q>', '<NOP>')
map({ 'n', 'v' }, 'H', '<NOP>')
@ -28,6 +33,10 @@ map({ 'n', 'v' }, '<leader>m', '<C-w>10>')
map({ 'n', 'v' }, '<leader>N', '<C-w>6-')
map({ 'n', 'v' }, '<leader>M', '<C-w>6+')
-- quickfix buffer
map('n', '<M-n>', ':cn<CR>', { silent = true })
map('n', '<M-p>', ':cp<CR>', { silent = true })
-- Remap <M-BS> to remove last word
map('i', '<M-BS>', '<C-w>')

View file

@ -16,7 +16,7 @@ vim.o.autoindent = true
vim.o.smartindent = true
vim.o.smarttab = true
vim.o.breakindent = true
vim.o.softtabstop = -1
vim.o.softtabstop = 4
-- Save undo history
vim.o.undofile = true

View file

@ -6,6 +6,8 @@ local servers = {
rust_analyzer = {},
bashls = {},
hls = {},
eslint = {},
ts_ls = {},
}
vim.lsp.set_log_level("debug")
@ -43,7 +45,15 @@ for server_name, config in pairs(servers) do
lspconfig[server_name].setup({
capabilities = capabilities,
on_attach = on_attach,
settings = { [server_name] = config },
settings = {
[server_name] = config ~= {} and {
settings = {
[server_name] = {
config
}
}
} or {}
},
})
end

View file

@ -1,10 +1,11 @@
return {
settings = {
['lua_ls'] = {
Lua = {
workspace = { checkThirdParty = false },
telemetry = { enable = false },
},
}
}
Lua = {
workspace = {
checkThirdParty = true,
library = {
vim.env.VIMRUNTIME
}
},
telemetry = { enable = false },
},
}

View file

@ -1,11 +1,13 @@
return {
'rcarriga/nvim-notify',
'psliwka/vim-smoothie',
'stefandtw/quickfix-reflector.vim',
'tpope/vim-sleuth',
{ 'akinsho/bufferline.nvim', opts = {}, dependencies = { 'navarasu/onedark.nvim' } },
{ 'ethanholz/nvim-lastplace', opts = {} },
{ 'kylechui/nvim-surround', version = '*', event = 'VeryLazy', opts = {} },
{ 'lukas-reineke/indent-blankline.nvim', main = 'ibl', opts = {} },
{ 'norcalli/nvim-colorizer.lua', opts={'*'}, dependencies = { 'navarasu/onedark.nvim' } },
{ 'norcalli/nvim-colorizer.lua', opts={ '*' }, dependencies = { 'navarasu/onedark.nvim' } },
{ 'wakatime/vim-wakatime', event = 'VeryLazy' },
{ 'williamboman/mason.nvim', opts = {} },
}

View file

@ -36,6 +36,6 @@ return {
vim.keymap.set('n', '<leader>of', require('telescope.builtin').oldfiles)
vim.keymap.set('n', '<leader>af', require('telescope.builtin').git_files)
vim.keymap.set('n', '<leader>sf', require('telescope.builtin').find_files)
vim.keymap.set('n', '<leader>sw', require('telescope.builtin').grep_string)
vim.keymap.set('n', '<leader>fw', require('telescope.builtin').grep_string)
end
}

View file

@ -3,11 +3,9 @@ return {
opts = {},
cmd = "Trouble",
keys = {
{ "<leader>xx", "<cmd>Trouble diagnostics toggle<cr>" }, -- ??
{ "<leader>xX", "<cmd>Trouble diagnostics toggle filter.buf=0<cr>" }, -- useless?
{ "<leader>cs", "<cmd>Trouble symbols toggle focus=false<cr>" }, -- nice as well
{ "<leader>cl", "<cmd>Trouble lsp toggle focus=false win.position=right<cr>" }, -- nicee
{ "<leader>xL", "<cmd>Trouble loclist toggle<cr>" }, -- ??
{ "<leader>xQ", "<cmd>Trouble qflist toggle<cr>" }, -- ??
{ "<leader>ew", "<cmd>Trouble diagnostics toggle<cr>" },
{ "<leader>ef", "<cmd>Trouble diagnostics toggle filter.buf=0<cr>" },
{ "<leader>cs", "<cmd>Trouble symbols toggle focus=false<cr>" },
{ "<leader>cl", "<cmd>Trouble lsp toggle focus=false win.position=right<cr>" },
},
}

View file

@ -1,15 +0,0 @@
local M = { }
function M.close_buffer(force)
if #vim.fn.filter(vim.fn.range(1, vim.fn.bufnr '$'), 'buflisted(v:val)') <= 1 then
vim.api.nvim_command("qa" .. (force and "!" or ""))
else
local tree = require("nvim-tree.api").tree
tree.toggle({ focus = false })
vim.api.nvim_command("bd" .. (force and "!" or ""))
tree.toggle({ focus = false })
end
end
return M

View file

@ -1,18 +0,0 @@
local M = { }
function M.lazy_init()
local lazypath = vim.fn.stdpath 'data' .. '/lazy/lazy.nvim'
if not vim.loop.fs_stat(lazypath) then
vim.fn.system {
'git',
'clone',
'--filter=blob:none',
'https://github.com/folke/lazy.nvim.git',
'--branch=stable',
lazypath,
}
end
vim.opt.rtp:prepend(lazypath)
end
return M

View file

@ -21,8 +21,8 @@ bind ';' "command-prompt"
bind C-r "source-file ~/.config/tmux/tmux.conf"
# Session binds
bind C-n "new-session -c '#{pane_current_path}' -s '#{b:pane_current_path}'"
bind C-x "set-option -g detach-on-destroy on; kill-session"
# bind C-n "new-session -c '#{pane_current_path}' -s '#{b:pane_current_path}'"
# bind C-x "set-option -g detach-on-destroy on; kill-session"
bind X "set-option -g detach-on-destroy off; kill-session; set-option -g detach-on-destroy on"
# Select mode

View file

@ -9,8 +9,8 @@ set -g @batt_icon_charge_tier6 ' '
set -g @batt_icon_charge_tier5 ' '
set -g @batt_icon_charge_tier4 ' '
set -g @batt_icon_charge_tier3 ' '
set -g @batt_icon_charge_tier2 ''
set -g @batt_icon_charge_tier1 '! !'
set -g @batt_icon_charge_tier2 ''
set -g @batt_icon_charge_tier1 ''
# better-mouse-mode
set -g @emulate-scroll-for-no-mouse-alternate-buffer "on"

View file

@ -13,10 +13,11 @@ set -g status-justify "left"
# status
set -g status-left-length 0
set -g status-left "#[bg=#{@theme-active-bg},fg=#{@theme-active-fg}]#{?client_prefix,[#{session_name}],#[bg=#{@theme-bg},fg=#{@theme-fg}][#{session_name}]}#[bg=#{@theme-bg},fg=#{@theme-fg}] "
set -g status-right "#{battery_icon_charge} #{battery_percentage} | %a %m/%d %I:%M %P"
set -g status-right "#(sb-battery -s) | %a %m/%d %I:%M %P"
set -g window-status-format " #I:#W "
set -g window-status-current-format "#[bg=#{@theme-active-bg},fg=#{@theme-active-fg}, bold]#{?window_zoomed_flag, #I:#W 󰊓 , #I:#W }"
set -g window-status-style "bg=#{@theme-bg},fg=#{@theme-fg}"
set -g status-interval "5"
# pane styles
set -g pane-border-style "fg=#{@theme-active-bg}"

View file

@ -28,6 +28,9 @@ setw -g pane-base-index 1
set -g visual-activity off
set -g monitor-activity off
# number windows with respect for base-index
set -g renumber-windows on
# Resize all windows to max size?
setw -g aggressive-resize on

View file

@ -1,4 +1,5 @@
# if [ -z "$SSH_AUTH_SOCK" ]; then
# eval "$(ssh-agent -s)"
# fi
systemctl --user import-environment XDG_CURRENT_DESKTOP

View file

@ -1,7 +1,7 @@
set -a
PATH="$HOME/.local/share/go/bin:$PATH"
PATH="${$(find -L ~/.local/bin -type d -printf %p:)%%:}:$PATH"
PATH="${$(find -L ~/.local/bin ! -name '.*' -type d -printf %p:)%%:}:$PATH"
# lc vars
LANGUAGE="en_US.UTF-8"
@ -26,11 +26,6 @@ GPG_TTY="$(tty)"
MANPAGER="sh -c 'col -bx | batcat -l man -p'"
MANROFFOPT="-c"
MTR_OPTIONS="-t"
MOZ_USE_XINPUT2=1
XDG_CURRENT_DESKTOP="gtk"
XDG_SESSION_DESKTOP="$XDG_CURRENT_DESKTOP"
WINDOW_MANAGER="dwm"
SUDO_ASKPASS="${HOME}/.local/bin/scripts/dmenu_askpass"
SSH_ASKPASS="${HOME}/.local/bin/scripts/ssh-askpass"

View file

@ -1,8 +1,7 @@
[[ $- != *i* ]] && return
[ "$TERM" = "linux" ] && export TERM=fbterm
# [[ $- != *i* ]] && return # idk why would it be tho...
. ~/.cargo/env
. ~/.config/zsh/modes.sh
# ls colors
eval "$(dircolors -b)"
@ -86,6 +85,7 @@ alias 7z="7zz" # for whatever reason 7z provides 7zz binary in debian
alias wt="watch -d -cn 0.1 "
alias cal="ncal -b"
alias .e="source .env"
alias tp="taskell ${HOME}/.projects.md"
# function aliases
bl() { brightnessctl set "$1"% &> /dev/null; }
@ -126,4 +126,4 @@ alias ta="tmux a -t"
stty -ixon
# print tasks on startup
cat ~/.taskell.md
cat ~/.taskell.md | grep -v '>.*'

62
.config/zsh/modes.sh Normal file
View file

@ -0,0 +1,62 @@
mode::enable() {
local mode_path="${HOME}/.config/zsh/modes/$1.sh"
[ ! -f "$mode_path" ] && echo "Mode not found!" && return 1
export MODE__ACTIVE_MODE="$1"
export MODE__OLD_PS1="$PS1"
export PS1="($1) $PS1"
# shellcheck disable=SC1090
source "$mode_path"
}
mode::disable() {
export PS1="${MODE__OLD_PS1}"
local mode_path="${HOME}/.config/zsh/modes/$MODE__ACTIVE_MODE.sh"
unset -v "MODE__OLD_PS1"
unset -v "MODE__ACTIVE_MODE"
for mode_variable in $(perl -ne '/^(?>declare\s+(?>--?\w+\s*)+\s*)?\s*([\x21-\x3c\x3e-\x7e]+)=.*$/ && print "$1\n"' < "$mode_path"); do
unset "$mode_variable"
done
for mode_function in $(perl -ne '/^(?>function\s+)?([\x21-\x7e]+)\s*\(\)/ && print "$1\n"' < "$mode_path"); do
unset -f "$mode_function"
done
for mode_alias in $(perl -ne '/^alias ([\x21-\x3c\x3e-\x7e]+)=/ && print "$1\n"'< "$mode_path"); do
unalias "$mode_alias"
done
}
mode::help() {
echo "USAGE"
echo " mode [-h]"
echo " mode <MODENAME>"
echo " mode"
echo
echo "OPTIONS"
echo " -h for help lol"
echo
echo "AVAILABLE MODES"
for mode in ~/.config/zsh/modes/*; do
printf " %s\n" "$(basename "${mode%.sh}")"
done
}
m() {
[ -n "$MODE__ACTIVE_MODE" ] && mode::disable && return
local cmd="${1:?}"
case "$cmd" in
"-h"|"--help")
mode::help
;;
*)
mode::enable "$cmd" || mode::help >&2
;;
esac
}

18
.config/zsh/modes/cpp.sh Normal file
View file

@ -0,0 +1,18 @@
# shellcheck disable=SC2139
CPP_MODE__BUILD_DIR="./cmake-build"
alias cb="cmake --build ${CPP_MODE__BUILD_DIR}"
alias cg="cmake -B ${CPP_MODE__BUILD_DIR} -DCMAKE_EXPORT_COMPILE_COMMANDS=1 && ln -sf ${CPP_MODE__BUILD_DIR}/compile_commands.json ."
cpp_mode::find_exec() {
find "${CPP_MODE__BUILD_DIR}/$1" -maxdepth 1 -type f -executable
}
ct() {
eval "$(cpp_mode::find_exec "tests")"
}
cr() {
eval "$(cpp_mode::find_exec)"
}

View file

@ -1,6 +1,6 @@
#!/bin/bash
API_ENDPOINT='http://ip-api.com/json/?fields=7876383'
API_ENDPOINT="http://ip-api.com/json/$1"'?fields=7876383'
printf "%s" "$(curl "${API_ENDPOINT}" 2>/dev/null)" | jq -r '[ "IP: \(.query)", "Country: \(.country)", "City: \(.city)", "ISP: \(.isp)", "ASN: \(.as)" ][] | "\(.)"'
# vim: ft=bash

View file

@ -35,6 +35,7 @@ main() {
"--variable=published_time=$(date -Iseconds -d"$(stat "$1" | grep 'Birth:' | sed 's/.*Birth:\s//')")"
)
pandoc "${pandoc_options[@]}" <(shift_header "$1") > "$FILENAME" 2>/dev/null &&
echo "$FILENAME" &&
firefox "$FILENAME" 2>/dev/null & disown
sleep 5

320
.local/bin/scripts/my.itmo Executable file
View file

@ -0,0 +1,320 @@
#!/bin/sh
# shellcheck disable=all
"exec" "${HOME}/.local/share/venv/statusbar/bin/python3" "-u" "$0" "$@"
import datetime
import json
import os
import signal
import sys
import time
import traceback
from collections.abc import Callable
from dataclasses import dataclass
from typing import Literal, Any, TypeVar
from urllib.parse import urlparse
import requests
from bs4 import BeautifulSoup, Tag
EMOJI_BY_STATUS = {
0: '🟡',
1: '🟢',
2: '🔴',
}
TIMEOUT = 30
CONFIG_FILE = f"{os.environ['HOME']}/.my.itmo"
CACHE_FILE = f"{os.environ['HOME']}/.cache/my_itmo.cache"
SECRET_FILE = f"{os.environ['HOME']}/.secrets/my_itmo.secret"
PIPE_FILE = f"{os.environ['XDG_RUNTIME_DIR']}/my.itmo.pipe"
T = TypeVar('T')
def run_forever(fn: Callable, *args, **kwargs):
while True:
try:
fn(*args, **kwargs)
except Exception:
print(traceback.format_exc())
def run_until_successful(fn: Callable[..., T], *args, **kwargs) -> T:
while True:
try:
return fn(*args, **kwargs)
except Exception:
pass
else:
break # no it's not >( # pyright: ignore
def send_message(chat_id: int, text: str, token: str):
requests.post(f"https://api.telegram.org/bot{token}/sendMessage", data={
'chat_id': chat_id,
'parse_mode': 'HTML',
'text': text
})
@dataclass
class StatusObject:
id: int
name: str
notice: str
status: Literal[0, 1, 2]
status_name: str
updated_at: datetime.datetime
created_at: datetime.datetime
@staticmethod
def from_dict(data: dict[str, Any]):
data['updated_at'] = datetime.datetime.strptime(data['updated_at'].replace("+03:00", ''), '%Y-%m-%dT%H:%M:%S')
data['created_at'] = datetime.datetime.strptime(data['created_at'].replace("+03:00", ''), '%Y-%m-%dT%H:%M:%S')
return StatusObject(**data)
class ApiException(Exception):
status_code: int
body: str
def __init__(self, status_code: int, body: str):
super().__init__(status_code, body)
self.status_code = status_code
self.body = body
def __str__(self):
return f'Status code: {self.status_code}\nBody: {self.body}'
class Api:
_session: requests.Session
_username: str
_password: str
_access_token: str
_refresh_token: str
_expires_in: int
_refresh_expires_in: int
def __init__(self, username: str, password: str, *, access_token: str | None = None,
refresh_token: str | None = None, expires_in: int | None = None,
refresh_expires_in: int | None = None, cookies: Any | None = None):
self._session = requests.Session()
self._username = username
self._password = password
self._refresh_token = refresh_token if refresh_token else ''
self._expires_in = expires_in if expires_in else 0
self._refresh_expires_in = refresh_expires_in if refresh_expires_in else 0
if cookies: self._session.cookies.update(cookies)
self._access_token = access_token if access_token else ''
if access_token: self._session.headers.update({'Authorization': f'Bearer {access_token}'})
self._ensure_authorized()
def _first_auth(self):
self._session.headers.clear()
self._session.cookies.clear()
code_request = run_until_successful(self._session.get, 'https://id.itmo.ru/auth/realms/itmo/protocol/openid-connect/auth', params={
'protocol': 'oauth2',
'response_type': 'code',
'client_id': 'student-personal-cabinet',
'redirect_uri': 'https://my.itmo.ru/login/callback',
'scope': 'openid profile',
}, timeout=2)
soup = BeautifulSoup(code_request.text, features='html.parser')
form = soup.find('form')
if not isinstance(form, Tag):
raise ApiException(code_request.status_code, code_request.text)
url = form.get_attribute_list('action')[0]
auth_request = run_until_successful(self._session.post, url, data={'username': self._username, 'password': self._password})
if auth_request.status_code != 200:
raise ApiException(auth_request.status_code, auth_request.text)
parsed_url_params = {a.split('=')[0]: a.split('=')[1] for a in urlparse(auth_request.url).query.split('&')}
self._get_and_save_tokens({
'code' : parsed_url_params['code'],
'client_id': 'student-personal-cabinet',
'redirect_uri': 'https://my.itmo.ru/login/callback',
'audience': '',
'response_type': 'code',
'grant_type': 'authorization_code',
'code_verifier': ''
})
def _renew(self):
self._session.headers.clear()
self._session.cookies.clear()
self._get_and_save_tokens({
'refresh_token': self._refresh_token,
'scopes': 'openid profile',
'client_id': 'student-personal-cabinet',
'grant_type': 'refresh_token'
})
def _get_and_save_tokens(self, data: Any):
tokens_request = run_until_successful(self._session.post, 'https://id.itmo.ru/auth/realms/itmo/protocol/openid-connect/token', data=data, timeout=2)
if tokens_request.status_code != 200:
raise ApiException(tokens_request.status_code, tokens_request.text)
tokens = tokens_request.json()
self._access_token = tokens['access_token']
self._expires_in = int(time.time()) + tokens['expires_in'] - 10
self._refresh_expires_in = int(time.time()) + tokens['refresh_expires_in'] - 10
self._refresh_token = tokens['refresh_token']
self._session.headers.update({"Authorization": f"Bearer {tokens_request.json()['access_token']}"})
def _ensure_authorized(self):
current_time = int(time.time())
if self._access_token and self._expires_in > current_time:
return
elif self._refresh_token and self._refresh_expires_in > current_time:
self._renew()
else:
self._first_auth()
def get_status_list(self):
self._ensure_authorized()
r = run_until_successful(self._session.get, 'https://my.itmo.ru/api/requests/my', timeout=2)
if r.status_code != 200 or r.json()['error_code'] != 0:
raise ApiException(r.status_code, r.text)
return [StatusObject.from_dict(obj) for obj in r.json()['result']]
def to_dict(self) -> Any:
return {
'username': self._username,
'password': self._password,
'access_token': self._access_token,
'refresh_token': self._refresh_token,
'expires_in': self._expires_in,
'refresh_expires_in': self._refresh_expires_in,
'cookies': self._session.cookies.get_dict()
}
@staticmethod
def from_dict(data: Any):
return Api(
data['username'],
data['password'],
access_token = data['access_token'],
refresh_token = data['refresh_token'],
expires_in = data['expires_in'],
refresh_expires_in = data['refresh_expires_in'],
cookies = data['cookies'],
)
def listen_for_messages(api: Api, timeout=TIMEOUT, filter_func: Callable[[StatusObject], bool] | None = None):
prev_msg = None
while True:
msg = list(filter(filter_func, api.get_status_list()))
if not msg or msg == prev_msg:
time.sleep(timeout)
continue
prev_msg = msg
yield msg
time.sleep(timeout)
format_status = lambda status: f"{EMOJI_BY_STATUS[status.status]} {status.notice.split('.')[0].strip()}"
format_message = lambda status: f"{EMOJI_BY_STATUS[status.status]} <b>{status.name}</b>\n\n{status.notice}"
class IDsFilter:
_ids: list[str]
_update_time: float
def __init__(self):
self._ids = []
self._update_dict()
def __call__(self, status: StatusObject) -> bool:
if self._update_time + TIMEOUT < time.time():
self._update_dict()
return str(status.id) in self._ids
def _update_dict(self):
self._update_time = time.time()
try:
with open(CONFIG_FILE) as file:
self._ids = file.read().strip().replace(' ', '').split(',')
except Exception:
self._ids = []
class LastUpdateFilter:
_update_time: datetime.datetime
def __init__(self, ignore_now = False) -> None:
self._update_time = datetime.datetime.fromtimestamp(0) if not ignore_now else datetime.datetime.now()
def __call__(self, status: StatusObject):
return status.updated_at >= self._update_time
def update(self):
self._update_time = datetime.datetime.now()
def main():
api = None
if os.path.isfile(CACHE_FILE):
with open(CACHE_FILE) as file:
api = Api.from_dict(json.load(file))
if os.path.isfile(SECRET_FILE):
with open(SECRET_FILE) as secret_file:
data = json.load(secret_file)
owner_id = data['owner_id']
bot_token = data['bot_token']
if not api:
api = Api(data['username'], data['password'])
else:
print("Missing secret file!", file=sys.stderr)
exit(1)
def die(*_):
with open(CACHE_FILE, 'w') as file:
json.dump(api.to_dict(), file)
if os.path.isfile(PIPE_FILE):
os.remove(PIPE_FILE)
exit(0)
signal.signal(signal.SIGTERM, die)
signal.signal(signal.SIGINT, die)
for message in listen_for_messages(api, filter_func=IDsFilter()):
with open(PIPE_FILE, 'w') as file:
print('\n'.join(map(format_status, message)))
file.write(' '.join(map(format_status, message)))
# update_filter = LastUpdateFilter(ignore_now=True)
# for message in listen_for_messages(api, filter_func=update_filter):
# formatted_messages = list(map(format_message, message))
# print('\n---\n'.join(formatted_messages))
# for message in formatted_messages:
# send_message(owner_id, message, bot_token)
# update_filter.update()
if __name__ == "__main__":
run_forever(main)
# vim: ft=python

90
.local/bin/scripts/tg Executable file
View file

@ -0,0 +1,90 @@
#!/bin/bash
{ read -r _TELEGRAM__BOT_TOKEN; read -r _TELEGRAM__USER_ID; } < "${HOME}/.secrets/telegram.secret"
declare -A _TELEGRAM__PARSE_MODES=(
[md]=MarkdownV2
[html]=HTML
)
declare -A tg__params=()
tg__code=0
tg::send_message() {
declare -a curl_params=()
for name in "${!tg__params[@]}"; do
curl_params+=("--data-urlencode" "$name=${tg__params[$name]}")
done
while IFS= read -d '' -n 4096 -r chunk; do
[ ${tg__code} -eq 1 ] &&
txt=(--data-urlencode "text=<pre>${chunk}</pre>") ||
txt=(--data-urlencode "text=${chunk}")
curl -X POST "https://api.telegram.org/bot${_TELEGRAM__BOT_TOKEN}/sendMessage" \
--data-urlencode "chat_id=$_TELEGRAM__USER_ID" \
"${curl_params[@]}" \
"${txt[@]}"
done
[ -n "$chunk" ] && {
[ ${tg__code} -eq 1 ] &&
txt=(--data-urlencode "text=<pre>${chunk}</pre>") ||
txt=(--data-urlencode "text=${chunk}")
curl -X POST "https://api.telegram.org/bot${_TELEGRAM__BOT_TOKEN}/sendMessage" \
--data-urlencode "chat_id=$_TELEGRAM__USER_ID" \
"${curl_params[@]}" \
"${txt[@]}"
}
}
(return 0 2>/dev/null) && return
help() {
echo "ABSTRACT"
echo " Read data from fd0 and send it to Telegram."
echo
echo "USAGE"
echo " tg [PARAMS]"
echo
echo "PARAMS"
echo " -c, --code Wrap text with <pre> tags"
echo " -h, --help Print this message"
echo " -p, --parse-mode Telegram parse mode (html, md)"
echo " -r, --print-response Don't silence Telegram response"
echo " --tg<NAME> <VALUE> Set POST parameter with NAME to VALUE"
}
die() {
echo "[ERROR] $1" >&2
echo
help
exit 1
}
main() {
while [ $# -gt 0 ]; do
case "$1" in
'-h'|'--help') help; exit 0 ;;
'-p'|'--parse-mode') shift; tg__params[parse_mode]="${_TELEGRAM__PARSE_MODES[$1]}" ;;
'-c'|'--code') tg__code=1; tg__params[parse_mode]='HTML' ;;
'-r'|'--print-response') print_response=1 ;;
'--tg'*) tg__params["${1#--tg}"]="$2"; shift ;;
esac
shift
done
[ -t 0 ] && die "Can't run on stdin!"
resp="$(tg::send_message "$@" 2>/dev/null)"
[ -n "${print_response:+_}" ] && echo "$resp"
[ "$(jq .ok <<<"$resp")" = "true" ] || jq <<< "$resp" >&2
}
main "$@"

View file

@ -10,40 +10,40 @@ trap 'die' SIGTERM SIGQUIT SIGINT
declare -a CONFIGS
for config in /etc/wireguard/*; do
config="$(basename "$config")"
CONFIGS+=("${config%.conf}")
config="$(basename "$config")"
CONFIGS+=("${config%.conf}")
done
COMMANDS=("up" "down")
die() {
rm $PIPE
exit 0
rm $PIPE
exit 0
}
in_arr() {
declare -n arr="$2"
declare -n arr="$2"
for value in "${arr[@]}"; do
[ "$value" = "$1" ] && return 0
done
return 1
for value in "${arr[@]}"; do
[ "$value" = "$1" ] && return 0
done
return 1
}
main() {
mkfifo $PIPE -m666
mkfifo $PIPE -m666
while :; do
read -r cmd ifname < $PIPE
while :; do
read -r cmd ifname < $PIPE
if ! in_arr "$ifname" "CONFIGS"; then
echo "ERROR: Invalid interface $ifname" > $PIPE
elif ! in_arr "$cmd" "COMMANDS"; then
echo "ERROR: Invalid command $cmd" > $PIPE
else
wg-quick "$cmd" "$ifname" > $PIPE 2>&1
fi
done
if ! in_arr "$ifname" "CONFIGS"; then
echo "ERROR: Invalid interface $ifname" > $PIPE
elif ! in_arr "$cmd" "COMMANDS"; then
echo "ERROR: Invalid command $cmd" > $PIPE
else
wg-quick "$cmd" "$ifname" > $PIPE 2>&1
fi
done
}
main

View file

@ -41,9 +41,9 @@ while [ "$#" -gt 0 ]; do
'-c'|'--create') OPERATION=c;;
'-d'|'--deactivate') OPERATION=d; return;;
'-r'|'--remove') OPERATION=r;;
'-f'|'--folder') shift; VENV_FOLDER_NAME="$1";;
'-f'|'--folder') shift; VENV_FOLDER_PATH="$1";;
-*) help; return;;
*) shift; VENV_FOLDER_PATH="$1";;
*) VENV_FOLDER_NAME="$1";;
esac
shift
done

View file

@ -4,22 +4,37 @@ shopt -s extglob
declare -a batteries
status_by_charge() {
capacity="$1"
if [ "$capacity" -ge 95 ]; then
echo ' '
elif [ "$capacity" -ge 65 ]; then
echo ' '
elif [ "$capacity" -ge 50 ]; then
echo ' '
elif [ "$capacity" -gt 20 ]; then
echo ' '
fi
}
for battery_path in /sys/class/power_supply/!(AC*); do
status="$(cat "${battery_path}/status")"
capacity="$(cat "${battery_path}/capacity")"
sep=$([ "$1" == "-s" ] && echo " ")
case "${status}" in
"Full") status_string="⚡" ;;
"Discharging") status_string="🔋" ;;
"Charging") status_string="🔌" ;;
"Not charging") status_string="🛑" ;;
"Unknown") status_string="♻️" ;;
*) status_string="??" ;;
"Full") status_symbol=" " ;;
"Discharging") status_symbol="$(status_by_charge "${capacity}")" ;;
"Charging") status_symbol="󱐥 " ;;
"Not charging") status_symbol="󱐤 " ;;
"Unknown") status_symbol="󰒲 " ;;
*) status_symbol="?? " ;;
esac
capacity="$(cat "${battery_path}/capacity")"
[ "$status" = "Discharging" ] && [ "$capacity" -le 25 ] && status_string="❗"
batteries+=("${status_string} ${capacity}%")
[ "$capacity" -eq 100 ] && status_symbol=" "
[ "$status" = "Discharging" ] && [ "$capacity" -le 20 ] && { status_symbol="❗"; [ -n "$sep" ] && sep="" || sep=" "; }
batteries+=("${status_symbol}${sep}${capacity}%")
done
echo "${batteries[@]}"

5
.local/bin/statusbar/sb-status Executable file
View file

@ -0,0 +1,5 @@
#!/bin/bash
FILEPATH="${XDG_RUNTIME_DIR}/my.itmo.pipe"
[ -f "${FILEPATH}" ] && cat "${FILEPATH}"

View file

@ -3,5 +3,5 @@
IFNAME="$(ip link show | grep 'wg_' | cut -d ' ' -f 2 | sed 's/://' | sed 's/wg_//' | tr '[:lower:]' '[:upper:]' | sed 's/_D/ (dpi)/')"
if [ -n "${IFNAME}" ]; then
echo "🛡️ ${IFNAME}"
echo "󰦝 ${IFNAME}"
fi

View file

@ -10,7 +10,8 @@ export XDG_CURRENT_DESKTOP="gtk"
export XDG_SESSION_DESKTOP="$XDG_CURRENT_DESKTOP"
export WINDOW_MANAGER="dwm"
exec ssh-agent "${HOME}"/.local/src/dwm/dwm
# exec ssh-agent /usr/bin/dwm
eval "$(ssh-agent)"
exec "${HOME}"/.local/src/dwm/dwm
# vim: ft=sh