diff --git a/.Brewfile b/.Brewfile new file mode 100644 index 0000000..d9f0c5b --- /dev/null +++ b/.Brewfile @@ -0,0 +1,23 @@ +brew "cmake" +brew "exiv2" +brew "ffmpeg" +brew "git-filter-repo" +brew "go" +brew "jpeg" +brew "leveldb" +brew "neovim" +brew "nmap" +brew "node" +brew "pass" +brew "podman" +brew "python@3.12" +brew "restic" +brew "samba" +brew "subfinder" +brew "yarn" +brew "yt-dlp" +brew "zoxide" +cask "amethyst" +cask "amorphousdiskmark" +cask "android-platform-tools" +cask "iterm2" diff --git a/.config/git/config b/.config/git/config new file mode 100755 index 0000000..256bed3 --- /dev/null +++ b/.config/git/config @@ -0,0 +1,28 @@ +[color] + diff = auto + status = auto + branch = auto + interactive = auto + ui = true + pager = true + submodule = true + fetch = true + pull = true +[push] + default = simple +[pull] + ff = only +[core] + excludesfile = ~/.gitignore + autocrlf = input +[status] + submoduleSummary = true +[pager] + log = less --chop-long-lines --shift 3 +[alias] + graph = log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold cyan)%aD%C(reset) %C(bold green)(%ar)%C(reset)%C(bold yellow)%d%C(reset)%n'' %C(white)%s%C(reset) %C(dim white)- %an%C(reset)' --all + chronograph = graph --date-order + ff = merge --ff-only + amend = commit --amend --reuse-message=HEAD +[init] + defaultBranch = main diff --git a/.environment.d/nas.env b/.environment.d/01_nas.env.skel similarity index 73% rename from .environment.d/nas.env rename to .environment.d/01_nas.env.skel index f4fdb3b..5a0b4fa 100644 --- a/.environment.d/nas.env +++ b/.environment.d/01_nas.env.skel @@ -1,3 +1,3 @@ -NAS_IP="192.168.84.3" +NAS_IP="127.0.0.1" NAS_USER="janolehuebner" NAS_TOKEN_NAME_IN_STORE="sudo-lana" diff --git a/.environment.d/git.env.skel b/.environment.d/git.env.skel new file mode 100644 index 0000000..eebccae --- /dev/null +++ b/.environment.d/git.env.skel @@ -0,0 +1,4 @@ +GIT_AUTHOR_NAME="" +GIT_AUTHOR_EMAIL="" +GIT_COMMITTER_NAME=$GIT_AUTHOR_NAME +GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL diff --git a/.environment.d/insta.env.skel b/.environment.d/insta.env.skel new file mode 100644 index 0000000..deca591 --- /dev/null +++ b/.environment.d/insta.env.skel @@ -0,0 +1,5 @@ +insta_share_on_nas="192....../DATA" +insta_path_on_nas="social/insta" +insta_cookiefile="" +insta_mount_point="$HOME/NAS/insta" +insta_default_users=(user_a user_b) diff --git a/.environment.d/path.env b/.environment.d/path.env index 95d194a..2320178 100644 --- a/.environment.d/path.env +++ b/.environment.d/path.env @@ -1,6 +1,10 @@ -# Add directories to PATH -export PATH="/opt/homebrew/bin:$PATH" export PATH="$HOME/.local/bin:$PATH" -export PATH="$HOME/Library/Python/3.9/bin:$PATH" export PATH="$HOME/.cargo/bin:$PATH" export PATH="$HOME/bin:$PATH" +if uname -r | grep -qi "truenas"; then + export PATH="/home/linuxbrew/.linuxbrew/bin:$PATH" +elif [[ "$OSTYPE" == darwin* ]]; then + export PATH="/opt/homebrew/bin:$PATH" + export PATH="$HOME/Library/Python/3.9/bin:$PATH" +fi + diff --git a/.environment.d/youtube.env b/.environment.d/youtube.env.skel similarity index 55% rename from .environment.d/youtube.env rename to .environment.d/youtube.env.skel index cf2c388..4deb20e 100644 --- a/.environment.d/youtube.env +++ b/.environment.d/youtube.env.skel @@ -1 +1,2 @@ TUBE_TOKEN_NAME_IN_STORE="tube.lan" +TUBE_DEFAULT_USERS=("a" "b") diff --git a/.gitignore b/.gitignore index 0f385d5..6316ddf 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ public/ dev/ keyfile.keyx *.log +.environment.d/01_nas.env diff --git a/.zprofile b/.zprofile index e4638f8..b562e80 100755 --- a/.zprofile +++ b/.zprofile @@ -1,15 +1,8 @@ -export PATH="$PATH:$HOME/.local/bin:$HOME/bin" - -# ── 2. Load .env files from ~/.environment.d/ ─────────────────── -# Automatically export all variables defined while sourcing .env files -setopt allexport -for file in ~/.environment.d/*.env(.N); do - source "$file" -done -unset file -unsetopt allexport - -# ── 3. Source ~/.zshrc (if this is a login shell sourcing a profile file) ─ -# In Zsh, this is unnecessary in most setups unless you separate login/init logic. +# Enable Powerlevel10k instant prompt. Should stay close to the top of ~/.zshrc. +# Initialization code that may require console input (password prompts, [y/n] +# confirmations, etc.) must go above this block; everything else may go below. +if [[ -r "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" ]]; then + source "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" +fi [[ -r ~/.zshrc ]] && source ~/.zshrc diff --git a/.zsh_functions/download.zsh b/.zsh_functions/download.zsh new file mode 100644 index 0000000..669dd90 --- /dev/null +++ b/.zsh_functions/download.zsh @@ -0,0 +1,111 @@ +if ! typeset -f ytr >/dev/null; then + +export PATH="$PATH:$HOME/.local/bin:$HOME/bin" + +# ── 2. Load .env files from ~/.environment.d/ ─────────────────── +# Automatically export all variables defined while sourcing .env files +setopt allexport +for file in ~/.environment.d/*.env(.N); do + source "$file" +done +unset file +unsetopt allexport + + + + +# Load a function that allows us to import other function definitions from +# the ZSH_FUNC_PATH without providing their exact location +source "$DOTFILES_DIR/.zsh_functions/autosource.sh" + +# Load the rest of the zsh configs in ~/.zshrc.d/ +setopt allexport +for file in ~/.zshrc.d/*.zsh(.N); do + source "$file" +done + +source ~/.zsh_functions/youtube.zsh +fi + +mdl () { +cwd=$(pwd) +share_on_nas="$NAS_IP/media" +path_on_nas="Music/__INBOX" +jelly_wait=150 +check_smb_mount() { + mount | grep -q "$mount_point" +} + +mount_point="$HOME/NAS/Music" +if [ ! -d "$mount_point" ]; then + echo "Creating mount point directory..." + mkdir -p "$mount_point" +fi + +if ! check_smb_mount; then + echo "Mounting SMB share..." + /sbin/mount_smbfs "smb://janolehuebner:$(pass sudo-lana)@$share_on_nas" "$mount_point" +fi + +if ! check_smb_mount; then + echo "Failed to mount SMB share. Exiting." + exit 1 +fi + +# Move to target directory +cd "$mount_point/$path_on_nas" + +echo "SMB share mounted successfully." +if [[ "$*" == *"tidal.com"* ]]; then + echo "TIDAL DETECTED" + uvx tidal-dl -l $* +else + echo "Using qobuz-dl via uvx at: $(which uvx)" + echo "QOBUZ URL: $*" + uvx qobuz-dl dl $* +fi + +echo "Unmounting SMB share..." +sleep 1 +/sbin/umount -f "$mount_point" +cd $cwd +#if declare -f jelly_rescan > /dev/null; then +# echo "Waiting $jelly_wait secs before triggering automatic library scan..." +# sleep $jelly_wait +# jelly_rescan +# echo "done" +#fi +} +d () { +local url="${1:-$(pbpaste)}" +local used_clipboard=0 + +if [[ -z "$url" ]]; then + echo "No URL provided and clipboard is empty." + return 1 +fi + +# Check if URL came from clipboard +if [[ -z "$1" ]]; then + echo "started via clipboard" + used_clipboard=1 +fi + +case "$url" in + (*youtube*|*youtu.be*) + echo "Detected YouTube URL: $url" + ytr "$url" + ;; + (*qobuz*) + echo "Detected Qobuz URL: $url" + mdl "$url" + if [[ $used_clipboard -eq 1 ]]; then + osascript -e "display dialog \"Done with Qobuz: $url\" buttons {\"OK\"}" + fi + ;; + (*) + echo "Unknown URL: $url" + ;; +esac +} + diff --git a/.zsh_functions/insta.zsh b/.zsh_functions/insta.zsh new file mode 100644 index 0000000..65c6fa3 --- /dev/null +++ b/.zsh_functions/insta.zsh @@ -0,0 +1,76 @@ +insta () { + local cwd=$(pwd) + check_smb_mount () { + /sbin/mount | grep -q "$insta_mount_point" + } + + local stories_only=false + local user_list=() + while [[ $# -gt 0 ]] + do + case "$1" in + --cron) + local random_wait=$((RANDOM % 1800)) + echo "--------------------------------------------" + echo "Waiting for $((random_wait / 60)) minutes..." + sleep $random_wait + stories_only=true + ;; + --stories) + stories_only=true + ;; + *) + user_list+=("$1") + ;; + esac + shift + done + + echo "-----$(date)------" + + local is_local_nas=false + if [[ "$NAS_IP" == "127.0.0.1" || "$NAS_IP" == "localhost" ]]; then + is_local_nas=true + fi + + if [ ! -d "$insta_mount_point" ]; then + echo "Creating mount point directory..." + mkdir -p "$insta_mount_point" + fi + + if ! $is_local_nas; then + if ! check_smb_mount; then + echo "Mounting SMB share..." + /sbin/mount_smbfs "smb://janolehuebner:$(pass sudo-lana 2>/dev/null)@$insta_share_on_nas" "$insta_mount_point" + fi + if ! check_smb_mount; then + echo "Failed to mount SMB share. Exiting." + return 1 + fi + fi + + cd "$insta_mount_point/$insta_path_on_nas" || return 1 + + if [[ ${#user_list[@]} -eq 0 ]]; then + user_list=("${insta_default_users[@]}") + fi + + #local cmd=(uvx --with browser_cookie3 instaloader -b Firefox -B '/Users/janolehuebner/Library/Application Support/zen/Profiles/frbi8zqc.insta/cookies.sqlite' "${user_list[@]}" --fast-update --abort-on=302,400,401,429) + local cmd=(uvx --with browser_cookie3 instaloader -b Safari "${user_list[@]}" --fast-update --abort-on=302,400,401,429) + if $stories_only; then + cmd+=(--stories --no-profile-pic --no-posts) + else + cmd+=(--stories --reels) + fi + + "${cmd[@]}" + + if ! $is_local_nas; then + echo "Unmounting SMB share..." + sleep 3 + /sbin/umount -f "$insta_mount_point" + fi + + cd "$cwd" +} + diff --git a/.zsh_functions/jellyfin.zsh b/.zsh_functions/jellyfin.zsh new file mode 100644 index 0000000..f8a6ab9 --- /dev/null +++ b/.zsh_functions/jellyfin.zsh @@ -0,0 +1,6 @@ +jelly_rescan(){ +JELLYFIN_URL="http://$NAS_IP:8096" +API_KEY="$(pass jelly)" +LIBRARY_ID="8a05b0252259a1dbd62df97522638439" +curl -X POST -H "X-Emby-Token: $API_KEY" "$JELLYFIN_URL/Items/$LIBRARY_ID/Refresh?Recursive=true" +} diff --git a/.zsh_functions/youtube.zsh b/.zsh_functions/youtube.zsh index f07a179..4651f39 100644 --- a/.zsh_functions/youtube.zsh +++ b/.zsh_functions/youtube.zsh @@ -29,7 +29,7 @@ ytr () { return 1 fi - local token="$(pass $TUBE_TOKEN_NAME_IN_STORE)" + local token="$(pass $TUBE_TOKEN_NAME_IN_STORE 2>/dev/null)" local json_data=$(jq -n --arg youtube_id "$youtube_id" '{ data: [ { @@ -58,7 +58,7 @@ yts() { fi # Set the token and URL - local token="$(pass $TUBE_TOKEN_NAME_IN_STORE)" + local token="$(pass $TUBE_TOKEN_NAME_IN_STORE 2>/dev/null)" # Initialize an empty array to store video data local video_data="[]" @@ -66,8 +66,8 @@ yts() { # Get the video IDs from yt-dlp and loop through each one while read -r youtube_id; do # Add each video ID to the array of data (accumulating in $video_data) - video_data=$(echo "$video_data" | jq --arg youtube_id "$youtube_id" '. + [{youtube_id: $youtube_id, status: "priority"}]') - done < <(yt-dlp "https://www.youtube.com/@$1/shorts" --flat-playlist --print "%(id)s") + video_data=$(echo "$video_data" | jq --arg youtube_id "$youtube_id" '. + [{youtube_id: $youtube_id, status: "pending"}]') + done < <(uvx yt-dlp "https://www.youtube.com/@$1/shorts" --flat-playlist --print "%(id)s") # Check if video_data is still an empty array (meaning no videos were found) if [[ "$video_data" == "[]" ]]; then @@ -90,13 +90,7 @@ yts() { # check_shorts() { - # List of channels to check (you can hardcode them or pass them as arguments) - channels=( - "DarkBlondii" - "littlesiha" - "lenaindica" - ) - + channels=("${TUBE_DEFAULT_USERS[@]}") # Loop through each channel and call yts for channel in "${channels[@]}"; do echo "Checking shorts for channel: $channel" diff --git a/.zshrc b/.zshrc index 4f22c1e..eb977ad 100755 --- a/.zshrc +++ b/.zshrc @@ -1,9 +1,15 @@ -# Enable Powerlevel10k instant prompt. Should stay close to the top of ~/.zshrc. -# Initialization code that may require console input (password prompts, [y/n] -# confirmations, etc.) must go above this block; everything else may go below. -if [[ -r "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" ]]; then - source "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" -fi +export PATH="$PATH:$HOME/.local/bin:$HOME/bin" +# ── 2. Load .env files from ~/.environment.d/ ─────────────────── +# Automatically export all variables defined while sourcing .env files +setopt allexport +for file in ~/.environment.d/*.env(.N); do + source "$file" +done +unset file +unsetopt allexport + + + # Load a function that allows us to import other function definitions from # the ZSH_FUNC_PATH without providing their exact location @@ -18,11 +24,13 @@ done unset file unsetopt allexport +autosource insta autosource youtube autosource milan autosource nas autosource fuck +autosource download +autosource jellyfin -test -e "${HOME}/.iterm2_shell_integration.zsh" && source "${HOME}/.iterm2_shell_integration.zsh" - +eval "$(zoxide init --cmd cd zsh)" diff --git a/.zshrc.d/aliases.zsh b/.zshrc.d/aliases.zsh index 3c8e267..d9a1746 100644 --- a/.zshrc.d/aliases.zsh +++ b/.zshrc.d/aliases.zsh @@ -1,12 +1,9 @@ # Aliases -alias d="$HOME/dev/bin/mdl" alias vim="nvim" alias vi="nvim" alias nano="nvim" alias tg="terragrunt" alias tf="tofu" alias terraform="tofu" -alias pip="pip3" -alias python="python3" -alias cookies="open $HOME/Library/Containers/com.apple.Safari/Data/Library/Cookies/" alias dotfiles="git --work-tree=$HOME --git-dir=$HOME/.dotgit " +alias instaloader="uvx --with browser_cookie3 instaloader" diff --git a/.zshrc.d/install_dotfiles.zsh b/.zshrc.d/install_dotfiles.zsh index 91ae7b6..419dd9b 100644 --- a/.zshrc.d/install_dotfiles.zsh +++ b/.zshrc.d/install_dotfiles.zsh @@ -19,4 +19,43 @@ install_dotfiles () { dotfiles_install_error="yes" fi fi + + if [[ ! -d ~/.oh-my-zsh ]]; then + sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended --keep-zshrc + git clone --depth=1 https://github.com/romkatv/powerlevel10k.git $HOME/.oh-my-zsh/themes/powerlevel10k + fi + + # Path to Brewfile + BREWFILE="$HOME/.Brewfile" + + if ! command -v brew &>/dev/null; then + echo "Homebrew not found. Installing..." + + if uname -r | grep -qi "truenas"; then + mkdir $HOME/linuxbrew + sudo ln -s $HOME/linuxbrew /home/linuxbrew + /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" + fi + + #----uv + command -v uv >/dev/null 2>&1 || curl -LsSf https://astral.sh/uv/install.sh | sh + # + + + if [[ "$OSTYPE" == "darwin"* ]]; then + + /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" + + + if [[ -f "$BREWFILE" ]]; then + echo "Installing from Brewfile: $BREWFILE" + brew bundle --file="$BREWFILE" + else + echo "No Brewfile found at $BREWFILE" + fi + fi + fi + + } +