first commit
This commit is contained in:
commit
aeb143ecb7
11 changed files with 535 additions and 0 deletions
52
kip
Executable file
52
kip
Executable file
|
@ -0,0 +1,52 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Function to install a package
|
||||||
|
install_package() {
|
||||||
|
package=$1
|
||||||
|
|
||||||
|
if mamba list | grep -q "^$package\s"; then
|
||||||
|
echo "Package '$package' already installed by mamba."
|
||||||
|
elif pip list | grep -q "^$package\s"; then
|
||||||
|
echo "Package '$package' already installed by pip."
|
||||||
|
else
|
||||||
|
echo "Installing package '$package'."
|
||||||
|
mamba install -y -c conda-forge "$package" || pip install "$package"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to process Python file for import statements
|
||||||
|
process_python_file() {
|
||||||
|
file_path=$1
|
||||||
|
# Extracting module names from import statements, handling both 'import' and 'from ... import ...'
|
||||||
|
IMPORTS=$(grep -E "^import |^from " "$file_path" | \
|
||||||
|
awk '{if($1=="from") print $2; else print $2}' | \
|
||||||
|
cut -d. -f1 | sort | uniq)
|
||||||
|
|
||||||
|
for package in $IMPORTS; do
|
||||||
|
echo "Processing $package from $file_path"
|
||||||
|
install_package $package
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if any arguments were passed
|
||||||
|
if [ "$#" -lt 1 ]; then
|
||||||
|
echo "Usage: kip <package1> [<package2> ...] or kip <script.py>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
MAMBA_BASE=$(mamba info --base)
|
||||||
|
export PYTHONPATH="${PYTHONPATH}:${MAMBA_BASE}/${CONDA_DEFAULT_ENV}/lib/python"
|
||||||
|
|
||||||
|
for arg in "$@"; do
|
||||||
|
# Check if the argument is a Python file
|
||||||
|
if [[ "$arg" == *.py ]]; then
|
||||||
|
if [ -f "$arg" ]; then
|
||||||
|
process_python_file "$arg"
|
||||||
|
else
|
||||||
|
echo "File $arg not found."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
install_package "$arg"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
116
noon
Executable file
116
noon
Executable file
|
@ -0,0 +1,116 @@
|
||||||
|
#!/Users/sij/miniforge3/bin/python
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
def ask_for_confirmation(message):
|
||||||
|
while True:
|
||||||
|
user_input = input(message + " (y/n): ").strip().lower()
|
||||||
|
if user_input in ('y', 'n'):
|
||||||
|
return user_input == 'y'
|
||||||
|
else:
|
||||||
|
print("Invalid input. Please enter 'y' or 'n'.")
|
||||||
|
|
||||||
|
def rename_files_orig(root_dir, manual):
|
||||||
|
for dirpath, _, filenames in os.walk(root_dir, followlinks=False):
|
||||||
|
for filename in filenames:
|
||||||
|
if '(orig)' in filename:
|
||||||
|
orig_filepath = os.path.join(dirpath, filename)
|
||||||
|
base_filename, ext = os.path.splitext(filename)
|
||||||
|
new_filename = base_filename.replace('(orig)', '')
|
||||||
|
new_filepath = os.path.join(dirpath, new_filename + ext)
|
||||||
|
|
||||||
|
if os.path.exists(new_filepath):
|
||||||
|
new_file_new_name = new_filename + '(new)' + ext
|
||||||
|
new_file_new_path = os.path.join(dirpath, new_file_new_name)
|
||||||
|
|
||||||
|
if manual:
|
||||||
|
if not ask_for_confirmation(f"Do you want to rename {new_filepath} to {new_file_new_path}?"):
|
||||||
|
continue
|
||||||
|
|
||||||
|
if os.path.exists(new_file_new_path):
|
||||||
|
print(f"Error: Cannot rename {new_filepath} to {new_file_new_path} because the target file already exists.")
|
||||||
|
continue
|
||||||
|
|
||||||
|
os.rename(new_filepath, new_file_new_path)
|
||||||
|
print(f'Renamed: {new_filepath} -> {new_file_new_name}')
|
||||||
|
else:
|
||||||
|
print(f"No associated file found for: {orig_filepath}")
|
||||||
|
|
||||||
|
orig_file_new_name = new_filename + ext
|
||||||
|
orig_file_new_path = os.path.join(dirpath, orig_file_new_name)
|
||||||
|
|
||||||
|
if manual:
|
||||||
|
if not ask_for_confirmation(f"Do you want to rename {orig_filepath} to {orig_file_new_path}?"):
|
||||||
|
continue
|
||||||
|
|
||||||
|
if os.path.exists(orig_file_new_path):
|
||||||
|
print(f"Error: Cannot rename {orig_filepath} to {orig_file_new_path} because the target file already exists.")
|
||||||
|
continue
|
||||||
|
|
||||||
|
os.rename(orig_filepath, orig_file_new_path)
|
||||||
|
print(f'Renamed: {orig_filepath} -> {orig_file_new_name}')
|
||||||
|
|
||||||
|
def rename_files_new(root_dir, manual):
|
||||||
|
for dirpath, _, filenames in os.walk(root_dir, followlinks=False):
|
||||||
|
for filename in filenames:
|
||||||
|
if '(new)' in filename:
|
||||||
|
new_filepath = os.path.join(dirpath, filename)
|
||||||
|
base_filename, ext = os.path.splitext(filename)
|
||||||
|
orig_filename = base_filename.replace('(new)', '')
|
||||||
|
orig_filepath = os.path.join(dirpath, orig_filename + ext)
|
||||||
|
|
||||||
|
if os.path.exists(orig_filepath):
|
||||||
|
orig_file_orig_name = orig_filename + '(orig)' + ext
|
||||||
|
orig_file_orig_path = os.path.join(dirpath, orig_file_orig_name)
|
||||||
|
|
||||||
|
if manual:
|
||||||
|
if not ask_for_confirmation(f"Do you want to rename {orig_filepath} to {orig_file_orig_path}?"):
|
||||||
|
continue
|
||||||
|
|
||||||
|
if os.path.exists(orig_file_orig_path):
|
||||||
|
print(f"Error: Cannot rename {orig_filepath} to {orig_file_orig_path} because the target file already exists.")
|
||||||
|
continue
|
||||||
|
|
||||||
|
os.rename(orig_filepath, orig_file_orig_path)
|
||||||
|
print(f'Renamed: {orig_filepath} -> {orig_file_orig_name}')
|
||||||
|
else:
|
||||||
|
print(f"No associated file found for: {new_filepath}")
|
||||||
|
|
||||||
|
new_file_new_name = orig_filename + ext
|
||||||
|
new_file_new_path = os.path.join(dirpath, new_file_new_name)
|
||||||
|
|
||||||
|
if manual:
|
||||||
|
if not ask_for_confirmation(f"Do you want to rename {new_filepath} to {new_file_new_path}?"):
|
||||||
|
continue
|
||||||
|
|
||||||
|
if os.path.exists(new_file_new_path):
|
||||||
|
print(f"Error: Cannot rename {new_filepath} to {new_file_new_path} because the target file already exists.")
|
||||||
|
continue
|
||||||
|
|
||||||
|
os.rename(new_filepath, new_file_new_path)
|
||||||
|
print(f'Renamed: {new_filepath} -> {new_file_new_name}')
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
parser = argparse.ArgumentParser(description='Rename files based on given criteria.')
|
||||||
|
parser.add_argument('-o', '--orig', action='store_true', help='Rename files ending with (orig)')
|
||||||
|
parser.add_argument('-n', '--new', action='store_true', help='Rename files ending with (new)')
|
||||||
|
parser.add_argument('-m', '--manual', action='store_true', help='Manual mode: ask for confirmation before each renaming')
|
||||||
|
parser.add_argument('directory', nargs='?', default=os.getcwd(), help='Directory to start the search (default: current directory)')
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if args.orig and args.new:
|
||||||
|
print("Error: Please specify either -o or -n, not both.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if args.orig:
|
||||||
|
print("Running in ORIG mode")
|
||||||
|
rename_files_orig(args.directory, args.manual)
|
||||||
|
elif args.new:
|
||||||
|
print("Running in NEW mode")
|
||||||
|
rename_files_new(args.directory, args.manual)
|
||||||
|
else:
|
||||||
|
print("Error: Please specify either -o or -n.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
40
nv
Executable file
40
nv
Executable file
|
@ -0,0 +1,40 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
SESSION_NAME="$1"
|
||||||
|
PYTHON_VERSION_INPUT="${2:-3.10}" # Default to 3.8 if not specified
|
||||||
|
|
||||||
|
# Normalize the Python version input
|
||||||
|
if [[ "$PYTHON_VERSION_INPUT" =~ ^python[0-9.]+$ ]]; then
|
||||||
|
PYTHON_VERSION="${PYTHON_VERSION_INPUT//python/}"
|
||||||
|
elif [[ "$PYTHON_VERSION_INPUT" =~ ^py[0-9.]+$ ]]; then
|
||||||
|
PYTHON_VERSION="${PYTHON_VERSION_INPUT//py/}"
|
||||||
|
else
|
||||||
|
PYTHON_VERSION="$PYTHON_VERSION_INPUT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Format for Conda
|
||||||
|
MAMBA_PYTHON_VERSION="python=$PYTHON_VERSION"
|
||||||
|
|
||||||
|
# Check if Conda environment exists
|
||||||
|
if ! mamba env list | grep -q "^$SESSION_NAME\s"; then
|
||||||
|
echo "Creating new Mamba environment: $SESSION_NAME with $MAMBA_PYTHON_VERSION"
|
||||||
|
mamba create --name "$SESSION_NAME" "$MAMBA_PYTHON_VERSION" --yes
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Find Conda env directory
|
||||||
|
CONDA_ENV_DIR=$(mamba env list | grep "^$SESSION_NAME" | awk '{print $2}')
|
||||||
|
|
||||||
|
# Handle tmux session
|
||||||
|
if ! tmux has-session -t "$SESSION_NAME" 2>/dev/null; then
|
||||||
|
echo "Creating new tmux session: $SESSION_NAME"
|
||||||
|
tmux new-session -d -s "$SESSION_NAME"
|
||||||
|
sleep 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Attach to tmux session and update PATH before activating Conda environment
|
||||||
|
sleep 1
|
||||||
|
tmux send-keys -t "$SESSION_NAME" "export PATH=\"$MAMBA_ENV_DIR/bin:\$PATH\"" C-m
|
||||||
|
tmux send-keys -t "$SESSION_NAME" "source ~/.zshrc" C-m
|
||||||
|
tmux send-keys -t "$SESSION_NAME" "mamba activate $SESSION_NAME" C-m
|
||||||
|
tmux attach -t "$SESSION_NAME"
|
||||||
|
|
46
serv
Executable file
46
serv
Executable file
|
@ -0,0 +1,46 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Check if an executable is provided as an argument
|
||||||
|
if [ -z "$1" ]; then
|
||||||
|
echo "Usage: $0 <executable>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Find the executable path using 'which'
|
||||||
|
EXEC_PATH=$(which "$1")
|
||||||
|
|
||||||
|
# Check if the executable exists
|
||||||
|
if [ -z "$EXEC_PATH" ]; then
|
||||||
|
echo "Error: Executable '$1' not found."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get the executable name
|
||||||
|
EXEC_NAME=$(basename "$EXEC_PATH")
|
||||||
|
|
||||||
|
# Create the launchd plist file content
|
||||||
|
PLIST_FILE_CONTENT="<?xml version=\"1.0\" encoding=\"UTF-8\"?>
|
||||||
|
<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">
|
||||||
|
<plist version=\"1.0\">
|
||||||
|
<dict>
|
||||||
|
<key>Label</key>
|
||||||
|
<string>$EXEC_NAME</string>
|
||||||
|
<key>ProgramArguments</key>
|
||||||
|
<array>
|
||||||
|
<string>$EXEC_PATH</string>
|
||||||
|
</array>
|
||||||
|
<key>KeepAlive</key>
|
||||||
|
<true/>
|
||||||
|
<key>RunAtLoad</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>"
|
||||||
|
|
||||||
|
# Create the launchd plist file
|
||||||
|
PLIST_FILE="$HOME/Library/LaunchAgents/$EXEC_NAME.plist"
|
||||||
|
echo "$PLIST_FILE_CONTENT" > "$PLIST_FILE"
|
||||||
|
|
||||||
|
# Load the launchd service
|
||||||
|
launchctl load "$PLIST_FILE"
|
||||||
|
|
||||||
|
echo "Service '$EXEC_NAME' has been created and loaded."
|
41
tmux-merge
Executable file
41
tmux-merge
Executable file
|
@ -0,0 +1,41 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Get the first session as the target for all panes
|
||||||
|
target_session=$(tmux list-sessions -F '#{session_name}' | head -n 1)
|
||||||
|
target_window="${target_session}:0" # assuming the first window is index 0
|
||||||
|
target_pane="${target_window}.0" # assuming the first pane is index 0
|
||||||
|
|
||||||
|
# Loop through each session
|
||||||
|
tmux list-sessions -F '#{session_name}' | while read session; do
|
||||||
|
# Skip the target session
|
||||||
|
if [[ "$session" == "$target_session" ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Loop through each window in the session
|
||||||
|
tmux list-windows -t "$session" -F '#{window_index}' | while read window; do
|
||||||
|
# Loop through each pane in the window
|
||||||
|
tmux list-panes -t "${session}:${window}" -F '#{pane_index}' | while read pane; do
|
||||||
|
source="${session}:${window}.${pane}"
|
||||||
|
# Check if the source is not the same as the target
|
||||||
|
if [[ "$source" != "$target_pane" ]]; then
|
||||||
|
# Join the pane to the target pane
|
||||||
|
tmux join-pane -s "$source" -t "$target_pane"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
# After moving all panes from a session, kill the now-empty session
|
||||||
|
# Check if the session to be killed is not the target session
|
||||||
|
if [[ "$session" != "$target_session" ]]; then
|
||||||
|
tmux kill-session -t "$session"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# After moving all panes, you may want to manually adjust the layout.
|
||||||
|
# For a simple automatic layout adjustment, you can use:
|
||||||
|
tmux select-layout -t "$target_window" tiled
|
||||||
|
|
||||||
|
# Attach to the master session after everything is merged
|
||||||
|
tmux attach-session -t "$target_session"
|
||||||
|
|
59
ts-new-node
Executable file
59
ts-new-node
Executable file
|
@ -0,0 +1,59 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# TSBINARY=$(which tailscale || echo "tailscale")
|
||||||
|
TSBINARY='/Applications/Tailscale.app/Contents/MacOS/Tailscale'
|
||||||
|
VERBOSE=0
|
||||||
|
|
||||||
|
# Check for -v argument
|
||||||
|
while getopts "v" option; do
|
||||||
|
case $option in
|
||||||
|
v)
|
||||||
|
VERBOSE=1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# Function to get exit node details
|
||||||
|
get_exit_node_details() {
|
||||||
|
if [[ $VERBOSE -eq 1 ]]; then
|
||||||
|
echo "$($TSBINARY exit-node list | awk '/'"$1"'/ {print $4", "$3" ("$2")"}')"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ $VERBOSE -eq 1 ]]; then
|
||||||
|
# Get the current exit node details and public IP
|
||||||
|
CURRENT_NODE=$(get_exit_node_details 'selected')
|
||||||
|
CURRENT_IP=$(curl -s ifconfig.me)
|
||||||
|
DNS_SERVER=$(python3 ~/.dns-info.py)
|
||||||
|
|
||||||
|
# Print the current node and IP
|
||||||
|
echo "IP address: $CURRENT_IP"
|
||||||
|
echo "DNS server: $DNS_SERVER"
|
||||||
|
echo "Exit node: ${CURRENT_NODE:-None}"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Select a new exit node
|
||||||
|
SELECTED_NODE=$($TSBINARY exit-node list | grep -v -f ~/.vpnblacklist | awk 'BEGIN {srand()} {print rand() " " $0}' | sort -k1,1n | cut -d ' ' -f2- | awk '{print $2}' | head -n 1)
|
||||||
|
|
||||||
|
# Set the selected node as the exit node
|
||||||
|
$TSBINARY set --exit-node="$SELECTED_NODE"
|
||||||
|
|
||||||
|
if [[ $VERBOSE -eq 1 ]]; then
|
||||||
|
# Wait for the network to update
|
||||||
|
sleep 1
|
||||||
|
|
||||||
|
# Get the new public IP
|
||||||
|
NEW_IP=$(curl -s ifconfig.me)
|
||||||
|
|
||||||
|
# Get the new exit node details
|
||||||
|
NEW_NODE=$(get_exit_node_details "$SELECTED_NODE")
|
||||||
|
|
||||||
|
NEW_DNS=$(python3 ~/.dns-info.py)
|
||||||
|
|
||||||
|
# Print the new node and IP
|
||||||
|
echo "New Public IP address: $NEW_IP"
|
||||||
|
echo "New DNS server: $NEW_DNS"
|
||||||
|
echo "Exit node: ${NEW_NODE:-None}"
|
||||||
|
echo ""
|
||||||
|
fi
|
3
ts-start
Executable file
3
ts-start
Executable file
|
@ -0,0 +1,3 @@
|
||||||
|
#!/bin/bash
|
||||||
|
export PATH=/opt/local/bin:/opt/local/sbin:/Users/sangye/.pyenv/shims:/Library/Frameworks/Python.framework/Versions/3.11/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/
|
||||||
|
sudo /opt/homebrew/bin/tailscaled --state=/var/lib/tailscale/tailscaled.state
|
3
ts-tmux
Executable file
3
ts-tmux
Executable file
|
@ -0,0 +1,3 @@
|
||||||
|
#!/bin/bash
|
||||||
|
export PATH=/opt/local/bin:/opt/local/sbin:/Users/sangye/.pyenv/shims:/Library/Frameworks/Python.framework/Versions/3.11/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/homebrew/bin:/Users/sangye/.local/bin
|
||||||
|
sudo tmux new-session -d -s tailscale 'ts-start'
|
75
uninstall
Executable file
75
uninstall
Executable file
|
@ -0,0 +1,75 @@
|
||||||
|
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Required parameters:
|
||||||
|
# @raycast.schemaVersion 1
|
||||||
|
# @raycast.title Uninstall App
|
||||||
|
# @raycast.mode fullOutput
|
||||||
|
|
||||||
|
# Optional parameters:
|
||||||
|
# @raycast.icon 🗑️
|
||||||
|
# @raycast.argument1 { "type": "text", "placeholder": "App name" }
|
||||||
|
|
||||||
|
# Documentation:
|
||||||
|
# @raycast.description Move an application and its related files to the Trash
|
||||||
|
|
||||||
|
app_name="$1"
|
||||||
|
|
||||||
|
move_to_trash() {
|
||||||
|
local file_path="$1"
|
||||||
|
osascript -e "tell application \"Finder\" to delete POSIX file \"$file_path\"" > /dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
uninstall_app() {
|
||||||
|
local app_name="$1"
|
||||||
|
|
||||||
|
if [[ ! "$app_name" =~ \.app$ ]]; then
|
||||||
|
app_name="${app_name}.app"
|
||||||
|
fi
|
||||||
|
|
||||||
|
local app_paths=$(mdfind "kMDItemKind == 'Application' && kMDItemDisplayName == '${app_name%.*}'")
|
||||||
|
|
||||||
|
if [ -z "$app_paths" ]; then
|
||||||
|
echo "Application not found. Please check the name and try again."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $(echo "$app_paths" | wc -l) -gt 1 ]; then
|
||||||
|
echo "Multiple applications found:"
|
||||||
|
select app_path in $app_paths; do
|
||||||
|
if [ -n "$app_path" ]; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
else
|
||||||
|
app_path=$app_paths
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Are you sure you want to move $app_path to the Trash?"
|
||||||
|
echo "Type 'yes' to confirm:"
|
||||||
|
read confirmation
|
||||||
|
if [ "$confirmation" != "yes" ]; then
|
||||||
|
echo "Uninstallation cancelled."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Moving $app_path to Trash"
|
||||||
|
move_to_trash "$app_path"
|
||||||
|
|
||||||
|
echo "Moving related files to Trash..."
|
||||||
|
local app_identifier=$(mdls -name kMDItemCFBundleIdentifier -r "$app_path")
|
||||||
|
if [ -n "$app_identifier" ]; then
|
||||||
|
find /Library/Application\ Support /Library/Caches /Library/Preferences ~/Library/Application\ Support ~/Library/Caches ~/Library/Preferences -name "*$app_identifier*" -maxdepth 1 -print0 | while IFS= read -r -d '' file; do
|
||||||
|
move_to_trash "$file"
|
||||||
|
done
|
||||||
|
else
|
||||||
|
echo "Couldn't find bundle identifier. Attempting to move files based on app name..."
|
||||||
|
find /Library/Application\ Support /Library/Caches /Library/Preferences ~/Library/Application\ Support ~/Library/Caches ~/Library/Preferences -name "*${app_name%.*}*" -maxdepth 1 -print0 | while IFS= read -r -d '' file; do
|
||||||
|
move_to_trash "$file"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Uninstallation complete. Files have been moved to the Trash."
|
||||||
|
}
|
||||||
|
|
||||||
|
uninstall_app "$app_name"
|
23
up
Executable file
23
up
Executable file
|
@ -0,0 +1,23 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Navigate to your project directory
|
||||||
|
cd ~/workshop/sijapi
|
||||||
|
|
||||||
|
# Pull the latest changes from the repository
|
||||||
|
echo "Pulling from main branch..."
|
||||||
|
git pull origin main
|
||||||
|
|
||||||
|
# Add changes to the Git index (staging area)
|
||||||
|
echo "Adding all changes..."
|
||||||
|
git add .
|
||||||
|
|
||||||
|
# Commit changes
|
||||||
|
echo "Committing changes..."
|
||||||
|
git commit -m "Auto-update: $(date)"
|
||||||
|
|
||||||
|
# Push changes to the remote repository
|
||||||
|
echo "Pushing all changes..."
|
||||||
|
git push origin main
|
||||||
|
|
||||||
|
echo "Update complete!"
|
||||||
|
|
77
vitals
Executable file
77
vitals
Executable file
|
@ -0,0 +1,77 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
tailscale='/Applications/Tailscale.app/Contents/MacOS/Tailscale'
|
||||||
|
|
||||||
|
# Get local IP
|
||||||
|
local_ip=$(hostname -I | awk '{print $1}')
|
||||||
|
wan_info=$(curl -s --max-time 10 https://am.i.mullvad.net/json)
|
||||||
|
wan_connected=false
|
||||||
|
if [ ! -z "$wan_info" ]; then
|
||||||
|
wan_connected=true
|
||||||
|
wan_ip=$(echo "$wan_info" | jq -r '.ip')
|
||||||
|
mullvad_exit_ip=$(echo "$wan_info" | jq '.mullvad_exit_ip')
|
||||||
|
blacklisted=$(echo "$wan_info" | jq '.blacklisted.blacklisted')
|
||||||
|
else
|
||||||
|
wan_ip="Unavailable"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if Tailscale is installed and get IP
|
||||||
|
if command -v $tailscale &> /dev/null; then
|
||||||
|
has_tailscale=true
|
||||||
|
tailscale_ip=$($tailscale ip -4)
|
||||||
|
# Get Tailscale exit-node information
|
||||||
|
ts_exitnode_output=$($tailscale exit-node list)
|
||||||
|
# Parse exit node hostname
|
||||||
|
if echo "$ts_exitnode_output" | grep -q 'selected'; then
|
||||||
|
mullvad_exitnode=true
|
||||||
|
# Extract the hostname of the selected exit node
|
||||||
|
mullvad_hostname=$(echo "$ts_exitnode_output" | grep 'selected' | awk '{print $2}')
|
||||||
|
else
|
||||||
|
mullvad_exitnode=false
|
||||||
|
mullvad_hostname=""
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
has_tailscale=false
|
||||||
|
tailscale_ip="Not installed"
|
||||||
|
mullvad_exitnode=false
|
||||||
|
mullvad_hostname=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
nextdns_info=$(curl -sL --max-time 10 https://test.nextdns.io)
|
||||||
|
if [ -z "$nextdns_info" ]; then
|
||||||
|
echo "Failed to fetch NextDNS status or no internet connection."
|
||||||
|
else
|
||||||
|
nextdns_status=$(echo "$nextdns_info" | jq -r '.status')
|
||||||
|
if [ "$nextdns_status" = "unconfigured" ]; then
|
||||||
|
echo "You are not using NextDNS."
|
||||||
|
nextdns_connected=false
|
||||||
|
nextdns_protocol=""
|
||||||
|
nextdns_client=""
|
||||||
|
else
|
||||||
|
nextdns_connected=true
|
||||||
|
nextdns_protocol=$(echo "$nextdns_info" | jq -r '.protocol')
|
||||||
|
nextdns_client=$(echo "$nextdns_info" | jq -r '.clientName')
|
||||||
|
echo "Connected to NextDNS via $nextdns_protocol. Client: $nextdns_client."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# read uptime_seconds _ < /proc/uptime
|
||||||
|
# uptime_days=$(echo "$uptime_seconds / 86400" | bc -l)
|
||||||
|
# uptime_rounded=$(printf "%.2f" $uptime_days)
|
||||||
|
|
||||||
|
cat <<EOF
|
||||||
|
{
|
||||||
|
"local_ip": "$local_ip",
|
||||||
|
"wan_connected": $wan_connected,
|
||||||
|
"wan_ip": "$wan_ip",
|
||||||
|
"has_tailscale": $has_tailscale,
|
||||||
|
"tailscale_ip": "$tailscale_ip",
|
||||||
|
"mullvad_exitnode": $mullvad_exitnode,
|
||||||
|
"mullvad_hostname": "$mullvad_hostname",
|
||||||
|
"mullvad_exit_ip": $mullvad_exit_ip,
|
||||||
|
"blacklisted": $blacklisted,
|
||||||
|
"nextdns_connected": $nextdns_connected,
|
||||||
|
"nextdns_protocol": "$nextdns_protocol",
|
||||||
|
"nextdns_client": "$nextdns_client",
|
||||||
|
"uptime": ""
|
||||||
|
}
|
Loading…
Reference in a new issue