Merge branch 'main' of ssh://gurgul.pro/artur/environment

This commit is contained in:
Artur Gurgul 2025-08-05 18:09:35 +02:00
commit 76bd8f782d
8 changed files with 307 additions and 0 deletions

28
bin/apas Executable file
View file

@ -0,0 +1,28 @@
#!/usr/bin/env bash
function lhash {
echo -n "${1}" | openssl dgst -sha512 | cut -d' ' -f2 | openssl dgst -md5 | cut -d' ' -f2
}
# Prompt user for input
read -p "Website: " url
read -p "Login: " login
read -s -p "Password: " password
echo
domain=$(echo "$url" | sed -E 's~https?://([^/]+).*~\1~')
hash=$(lhash "$login")
pass_path="web/${domain}/${hash}"
# Entry content
entry="${password}
url: ${url}
login: ${login}
"
echo "$entry" | pass insert -m "$pass_path"
# url
# login
# tags
# note

98
bin/cht Executable file
View file

@ -0,0 +1,98 @@
#!/usr/bin/env node
import path from "path"
import fs from "fs"
// DAT_ROOT should exists in ~/.zshrc-local
const indexPath = path.join(process.env["NOTES_DIR"], "")
const processFile = path.join(process.cwd(), process.argv[2])
const data = fs.readFileSync(processFile, 'utf8')
const jsonData = JSON.parse(data)
function wantSave(str) {
return typeof str == "string" && str.split("\n").length > 10
}
function saveToFileSync(content, file) {
const dir = path.dirname(file);
try {
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true })
}
fs.writeFileSync(file, content, 'utf8')
} catch (err) {
console.error('Error saving file:', err)
}
}
const toSave = jsonData.flatMap(o => {
const date = new Date(o.create_time * 1000)
// const formattedDate = date.toLocaleDateString('en-GB', {
// day: '2-digit',
// month: '2-digit',
// year: '2-digit',
// })
// return formattedDate
const day = String(date.getDate()).padStart(2, '0')
const month = String(date.getMonth() + 1).padStart(2, '0')
const year = String(date.getFullYear()).slice(-2)
let baseNotePath = path.join(indexPath, "gpt", `${day}-${month}-${year}`, `${o.title}`)
let conversations = []
for (const [key, value] of Object.entries(o.mapping)) {
//console.log(key, value)
conversations.push({
path: path.join(baseNotePath, `${key}.json`),
content: JSON.stringify(value, null, 2)
})
let parts = value?.message?.content.parts
if (Array.isArray(parts)) {
if (parts.length == 0) {
// skip
} else if (parts.length == 1) {
let fileName = path.join(baseNotePath, `${key}.md`)
let md = parts[0]
if (wantSave(md)) {
conversations.push({
path: fileName,
content: md
})
}
} else {
for (const [key, value] of parts.entries()) {
let fileName = path.join(baseNotePath, `${key}-${key+1}.md`)
let md = parts[key]
if (wantSave(md)) {
conversations.push({
path: fileName,
content: md
})
}
}
}
}
//process.exit(-1)
}
return conversations
})
for(const f of toSave) {
//for(const f of toSave.slice(0,5)) {
saveToFileSync(f.content,f.path)
}

57
bin/get Executable file
View file

@ -0,0 +1,57 @@
ARCHIVE=false
DESTINATION_LOCAL_DIR="./"
if [[ "$1" == "--archive" ]]; then
ARCHIVE=true
shift
fi
if [[ $# -lt 2 ]]; then
echo "Usage: $0 [--archive] user@host remote_source_dir [local_destination_dir]"
exit 1
fi
USER_HOST="$1"
REMOTE_USER="${USER_HOST%@*}"
HOST="${USER_HOST#*@}"
REMOTE_SOURCE_DIR="$2"
if [[ -n "$3" ]]; then
DESTINATION_LOCAL_DIR="$3"
fi
if [[ "$REMOTE_SOURCE_DIR" = /* ]]; then
IS_ABSOLUTE=true
else
IS_ABSOLUTE=false
fi
echo "ARCHIVE=$ARCHIVE"
echo "REMOTE_USER=$REMOTE_USER"
echo "HOST=$HOST"
echo "REMOTE_SOURCE_DIR=$REMOTE_SOURCE_DIR"
echo "DESTINATION_LOCAL_DIR=$DESTINATION_LOCAL_DIR"
REMOTE_BASE_DIR=""
if $IS_ABSOLUTE; then
REMOTE_BASE_DIR="/"
else
REMOTE_BASE_DIR=/home/$REMOTE_USER
fi
# Example that works
# ssh debian@gurgul.org "tar --zstd -cf - -C /home/debian .dat" | tar --zstd -xf - -C .
# get debian@gurgul.org .dat
# get --archive debian@gurgul.org /etc
TAR_COMMAND="tar --zstd -cf - -C $REMOTE_BASE_DIR $REMOTE_SOURCE_DIR"
if $ARCHIVE; then
ssh $REMOTE_USER@$HOST $TAR_COMMAND > "$DESTINATION_LOCAL_DIR/$(basename "$REMOTE_SOURCE_DIR")-$(date +"%d-%m-%Y").tar.zst"
else
ssh $REMOTE_USER@$HOST $TAR_COMMAND | tar --zstd -xf - -C $DESTINATION_LOCAL_DIR
fi

16
bin/index Executable file
View file

@ -0,0 +1,16 @@
#!/bin/bash
# find $NOTES_DIR/gpt -type d -path "$NOTES_DIR/gpt/[0-9][0-9]-[0-9][0-9]-[0-9][0-9]/*" | while read -r path; do
# echo $(basename "$path")
# done | sort -u | fzf
SEARCH_DIR="$NOTES_DIR/gpt"
DELIMITER="|"
selected=$(find "$SEARCH_DIR" -type d -path "$SEARCH_DIR/[0-9][0-9]-[0-9][0-9]-[0-9][0-9]/*" | while read -r path; do
topic=$(basename "$path")
echo -e "$topic\t$path"
done | fzf --delimiter='\t' --with-nth=1)
selected_path=$(echo "$selected" | cut -f2)
echo "Path: $selected_path"

View file

@ -6,4 +6,6 @@ if [[ "$OSTYPE" == "darwin"* ]]; then
elif [[ "$ARCH" == "x86_64" ]]; then
eval "$(/usr/local/bin/brew shellenv)"
fi
export PATH="$(brew --prefix ruby)/bin:$PATH"
fi

View file

@ -3,6 +3,9 @@
export PATH="$DAT_ROOT/bin:$HOME/.local/bin:$PATH"
export GEM_HOME="$HOME/.gems"
export GEM_PATH=$HOME/.gems
export RUBYLIB="$DAT_ROOT/lib"
export PASSWORD_STORE_DIR=$HOME/.local/lib/secure-vault/passwords

103
lib/archive.rb Normal file
View file

@ -0,0 +1,103 @@
require 'net/http'
require 'uri'
require 'open3'
require 'fileutils'
require 'open-uri'
require 'shellwords'
module Archive
MAGIC_NUMBERS = {
"\x1F\x8B" => 'gzip',
"\x50\x4B\x03\x04" => 'zip',
"\x28\xB5\x2F\xFD" => 'zstd',
"\xFD\x37\x7A\x58" => 'xz'
}
def self.fetch_and_extract(url, cache_path, destination_dir)
uri = URI.parse(url)
file_name = File.basename(uri.path)
archive_path = File.join(destination_dir, file_name)
format = detect_format_from_url(url)
puts "format #{format}"
download_file(uri, archive_path)
unless format
puts "case 1"
format = detect_format_from_headers(uri)
end
unless format
puts "case 2"
format = detect_format_from_magic(archive_path)
end
raise "Could not determine archive format" unless format
extract_archive(archive_path, format)
end
private
def self.detect_format_from_url(url)
case File.extname(url)
when '.gz', '.tgz' then 'gzip'
when '.zip' then 'zip'
when '.zst' then 'zstd'
when '.xz' then 'xz'
else nil
end
end
def self.detect_format_from_headers(uri)
response = Net::HTTP.get_response(uri)
content_type = response['content-type']
case content_type
when /gzip/ then 'gzip'
when /zip/ then 'zip'
when /zstd/ then 'zstd'
when /xz/ then 'xz'
else nil
end
end
def self.detect_format_from_magic(file_path)
File.open(file_path, 'rb') do |f|
bytes = f.read(4)
MAGIC_NUMBERS.each do |magic, format|
return format if bytes.start_with?(magic)
end
end
nil
end
def self.download_file(uri, output_path)
URI.open(uri) do |input|
File.open(output_path, 'wb') do |output|
IO.copy_stream(input, output)
end
end
end
def self.extract_archive(file_path, format)
case format
when 'gzip'
system("tar -xzf #{Shellwords.escape(file_path)}")
when 'zip'
system("unzip #{Shellwords.escape(file_path)}")
when 'zstd'
system("unzstd #{Shellwords.escape(file_path)}")
when 'xz'
# if file_path.end_with?('.tar.xz')
if `file #{Shellwords.escape(file_path)}`.include?('tar archive')
system("tar -xJf #{Shellwords.escape(file_path)}")
else
system("xz -dk #{Shellwords.escape(file_path)}")
end
else
raise "Unsupported archive format: #{format}"
end
end
end
# Example usage:
# fetch_and_extract("https://codeberg.org/forgejo/forgejo/releases/download/v12.0.1/forgejo-12.0.1-linux-amd64.xz")