minor updates
This commit is contained in:
parent
e3790a4f3f
commit
628baf3eea
32 changed files with 655 additions and 123 deletions
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
})
|
||||
|
|
|
@ -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>')
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
return {
|
||||
settings = {
|
||||
['lua_ls'] = {
|
||||
Lua = {
|
||||
workspace = { checkThirdParty = false },
|
||||
workspace = {
|
||||
checkThirdParty = true,
|
||||
library = {
|
||||
vim.env.VIMRUNTIME
|
||||
}
|
||||
},
|
||||
telemetry = { enable = false },
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 = {} },
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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>" },
|
||||
},
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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}"
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# if [ -z "$SSH_AUTH_SOCK" ]; then
|
||||
# eval "$(ssh-agent -s)"
|
||||
# fi
|
||||
|
||||
systemctl --user import-environment XDG_CURRENT_DESKTOP
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
62
.config/zsh/modes.sh
Normal 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
18
.config/zsh/modes/cpp.sh
Normal 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)"
|
||||
}
|
|
@ -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
|
|
@ -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
320
.local/bin/scripts/my.itmo
Executable 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
90
.local/bin/scripts/tg
Executable 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 "$@"
|
|
@ -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
|
||||
|
|
|
@ -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
5
.local/bin/statusbar/sb-status
Executable file
|
@ -0,0 +1,5 @@
|
|||
#!/bin/bash
|
||||
|
||||
FILEPATH="${XDG_RUNTIME_DIR}/my.itmo.pipe"
|
||||
|
||||
[ -f "${FILEPATH}" ] && cat "${FILEPATH}"
|
|
@ -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
|
||||
|
|
5
.xinitrc
5
.xinitrc
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue