Update 2025-04-13_15:16:39
This commit is contained in:
		
							
								
								
									
										68
									
								
								Fine-Tune_LoRA_GPU.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								Fine-Tune_LoRA_GPU.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,68 @@ | |||||||
|  | from transformers import AutoModelForCausalLM, AutoTokenizer, TrainingArguments, Trainer | ||||||
|  | from peft import LoraConfig, get_peft_model | ||||||
|  | from datasets import Dataset | ||||||
|  | import torch | ||||||
|  | import os | ||||||
|  |  | ||||||
|  | # Load model and tokenizer from HF | ||||||
|  | model_name = "Qwen/Qwen2.5-1.5B" | ||||||
|  | tokenizer = AutoTokenizer.from_pretrained(model_name) | ||||||
|  | model = AutoModelForCausalLM.from_pretrained(model_name, device_map="auto")  # GPU | ||||||
|  |  | ||||||
|  | # Prepare dataset: each .txt file as one example | ||||||
|  | content_dir = "./content" | ||||||
|  | texts = [] | ||||||
|  |  | ||||||
|  | for txt_file in os.listdir(content_dir): | ||||||
|  |     if txt_file.endswith(".txt"): | ||||||
|  |         with open(os.path.join(content_dir, txt_file), "r", encoding="utf-8") as tf: | ||||||
|  |             # Join all lines in the file into one text | ||||||
|  |             text = " ".join(line.strip() for line in tf.readlines() if line.strip()) | ||||||
|  |             texts.append(text) | ||||||
|  |  | ||||||
|  | dataset = Dataset.from_dict({"text": texts}) | ||||||
|  | print(f"Dataset size: {len(dataset)}")  # Should be ~300 | ||||||
|  |  | ||||||
|  | def tokenize_function(examples): | ||||||
|  |     # Tokenize the text | ||||||
|  |     tokenized = tokenizer(examples["text"], padding="max_length", truncation=True, max_length=128) | ||||||
|  |     # Create labels for causal LM | ||||||
|  |     tokenized["labels"] = tokenized["input_ids"].copy() | ||||||
|  |     return tokenized | ||||||
|  |  | ||||||
|  | tokenized_dataset = dataset.map(tokenize_function, batched=True, remove_columns=["text"]) | ||||||
|  |  | ||||||
|  | # Configure LoRA | ||||||
|  | lora_config = LoraConfig( | ||||||
|  |     r=8, | ||||||
|  |     lora_alpha=32, | ||||||
|  |     target_modules=["q_proj", "v_proj"], | ||||||
|  |     lora_dropout=0.1, | ||||||
|  | ) | ||||||
|  | model = get_peft_model(model, lora_config) | ||||||
|  |  | ||||||
|  | # Training arguments | ||||||
|  | training_args = TrainingArguments( | ||||||
|  |     output_dir="./fine_tuned_qwen2_5_1_5b", | ||||||
|  |     per_device_train_batch_size=8, | ||||||
|  |     gradient_accumulation_steps=1, | ||||||
|  |     num_train_epochs=5, | ||||||
|  |     learning_rate=2e-4, | ||||||
|  |     save_steps=50, | ||||||
|  |     logging_steps=10, | ||||||
|  |     fp16=True, | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | # Trainer | ||||||
|  | trainer = Trainer( | ||||||
|  |     model=model, | ||||||
|  |     args=training_args, | ||||||
|  |     train_dataset=tokenized_dataset, | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | # Fine-tune | ||||||
|  | trainer.train() | ||||||
|  |  | ||||||
|  | # Save | ||||||
|  | model.save_pretrained("./fine_tuned_qwen2_5_1_5b") | ||||||
|  | tokenizer.save_pretrained("./fine_tuned_qwen2_5_1_5b") | ||||||
							
								
								
									
										50
									
								
								f2b_status.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										50
									
								
								f2b_status.sh
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,50 @@ | |||||||
|  | #!/bin/bash | ||||||
|  | # ============================================================================= | ||||||
|  | # Script Name: f2b_status.sh | ||||||
|  | # Version: 1.6 | ||||||
|  | # Description: This script retrieves and displays the status of all Fail2Ban | ||||||
|  | #              jails, including error handling and logging. | ||||||
|  | # ============================================================================= | ||||||
|  |  | ||||||
|  | # Log file path | ||||||
|  | LOG_FILE="/var/log/fail2ban-status.log" | ||||||
|  |  | ||||||
|  | # Function to log messages with timestamp | ||||||
|  | log_message() { | ||||||
|  |     echo "$(date +"%Y-%m-%d %H:%M:%S") - $1" | tee -a "$LOG_FILE" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # Function to retrieve the list of jails | ||||||
|  | get_jail_list() { | ||||||
|  |     fail2ban-client status | grep 'Jail list:' | cut -d ":" -f2 | tr -d ',' | xargs | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # Retrieve the list of jails | ||||||
|  | log_message "Retrieving the list of Fail2Ban jails..." | ||||||
|  | JAIL_LIST=$(get_jail_list) | ||||||
|  |  | ||||||
|  | # Check if any jails were found | ||||||
|  | if [ -z "$JAIL_LIST" ]; then | ||||||
|  |     log_message "No jails found." | ||||||
|  |     exit 1 | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | # Convert JAIL_LIST into an array | ||||||
|  | IFS=' ' read -r -a JAIL_ARRAY <<< "$JAIL_LIST" | ||||||
|  |  | ||||||
|  | # Iterate over each jail and display its status | ||||||
|  | for JAIL in "${JAIL_ARRAY[@]}"; do | ||||||
|  |     log_message "Retrieving status for jail: $JAIL" | ||||||
|  |     STATUS=$(fail2ban-client status "$JAIL" 2>&1) | ||||||
|  |      | ||||||
|  |     if echo "$STATUS" | grep -q "Sorry but the jail"; then | ||||||
|  |         log_message "Failed to retrieve status for jail: $JAIL. Error: $STATUS" | ||||||
|  |     else | ||||||
|  |         log_message "Status for jail $JAIL retrieved successfully." | ||||||
|  |         echo "Status for jail: $JAIL" | ||||||
|  |         echo "$STATUS" | ||||||
|  |         echo "----------------------------" | ||||||
|  |     fi | ||||||
|  | done | ||||||
|  |  | ||||||
|  | log_message "Fail2Ban status check completed." | ||||||
							
								
								
									
										208
									
								
								gitea_push.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										208
									
								
								gitea_push.sh
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,208 @@ | |||||||
|  | #!/bin/zsh | ||||||
|  | # Script Version: 1.4 | ||||||
|  | # Description: Pushes the current folder (e.g. /etc) to a nested Gitea repo using provided nesting arguments. Auto-creates the remote repo via Gitea API if missing. | ||||||
|  |  | ||||||
|  | # Set variables | ||||||
|  | # ======== | ||||||
|  |  | ||||||
|  | # Try to extract GITEA_API_TOKEN from ~/.netrc if present | ||||||
|  | if [ -z "$GITEA_API_TOKEN" ] && grep -q '^GITEA_API_TOKEN=' ~/.netrc 2>/dev/null; then | ||||||
|  |   GITEA_API_TOKEN=$(grep '^GITEA_API_TOKEN=' ~/.netrc | head -n1 | cut -d= -f2 | xargs) | ||||||
|  |   export GITEA_API_TOKEN | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | GITEA_USER=$(awk '{for(i=1;i<=NF;i++) if($i=="login") print $(i+1)}' ~/.netrc | head -n1) | ||||||
|  | if [ -z "$GITEA_USER" ]; then | ||||||
|  |   echo "[ERROR] No login found in ~/.netrc" | ||||||
|  |   exit 1 | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | GITEA_URL="https://$(awk '{for(i=1;i<=NF;i++) if($i=="machine") print $(i+1)}' ~/.netrc | head -n1)" | ||||||
|  | if [ -z "$GITEA_URL" ]; then | ||||||
|  |   echo "[ERROR] No URL found in ~/.netrc" | ||||||
|  |   exit 1 | ||||||
|  | fi | ||||||
|  | GITEA_API_URL="$GITEA_URL/api/v1" | ||||||
|  |  | ||||||
|  | PRIVATE=false | ||||||
|  | DEBUG=false | ||||||
|  | COMMIT_MESSAGE="Update $(date +%F_%T)" | ||||||
|  |  | ||||||
|  | # Logging function | ||||||
|  | # ======== | ||||||
|  | log() { | ||||||
|  |   local level="$1"; shift | ||||||
|  |   if [ "$level" = "DEBUG" ] && [ "$DEBUG" != true ]; then return; fi | ||||||
|  |   local color_reset="$(tput sgr0)" | ||||||
|  |   local color="" | ||||||
|  |   case "$level" in | ||||||
|  |     INFO) color="$(tput setaf 2)" ;;    # green | ||||||
|  |     WARNING) color="$(tput setaf 3)" ;; # yellow | ||||||
|  |     ERROR) color="$(tput setaf 1)" ;;   # red | ||||||
|  |     DEBUG) color="$(tput setaf 4)" ;;   # blue | ||||||
|  |   esac | ||||||
|  |   echo "${color}[$level] $*${color_reset}" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # Functions | ||||||
|  | # ======== | ||||||
|  | create_repo() { | ||||||
|  |   log INFO "Repository does not exist. Creating via API: $REMOTE_PATH" | ||||||
|  |   log DEBUG "POST $GITEA_API_URL/user/repos with name=$REMOTE_PATH and private=$PRIVATE" | ||||||
|  |   RESPONSE=$(curl -s -X POST \ | ||||||
|  |     -H "Authorization: token $GITEA_API_TOKEN" \ | ||||||
|  |     -H "Content-Type: application/json" \ | ||||||
|  |     -d "{\"name\": \"$FOLDER_NAME\", \"private\": $PRIVATE}" \ | ||||||
|  |     "$GITEA_API_URL/user/repos") | ||||||
|  |  | ||||||
|  |   if echo "$RESPONSE" | grep -q '"clone_url"'; then | ||||||
|  |     log INFO "Remote repository created successfully." | ||||||
|  |   else | ||||||
|  |     log ERROR "Failed to create remote repository: $RESPONSE" | ||||||
|  |     exit 1 | ||||||
|  |   fi | ||||||
|  | } | ||||||
|  |  | ||||||
|  | prepare_commit() { | ||||||
|  |   git add . | ||||||
|  |   if ! git rev-parse --verify HEAD >/dev/null 2>&1; then | ||||||
|  |     log INFO "Creating initial commit" | ||||||
|  |     git commit -m "$COMMIT_MESSAGE" | ||||||
|  |   else | ||||||
|  |     log INFO "Committing changes" | ||||||
|  |     git commit -m "$COMMIT_MESSAGE" || log INFO "Nothing to commit" | ||||||
|  |   fi | ||||||
|  | } | ||||||
|  |  | ||||||
|  | setup_remote() { | ||||||
|  |   if git remote | grep -q '^origin$'; then | ||||||
|  |     log INFO "Updating remote origin URL" | ||||||
|  |     git remote set-url origin "$GIT_REMOTE" | ||||||
|  |   else | ||||||
|  |     log INFO "Adding remote origin" | ||||||
|  |     git remote add origin "$GIT_REMOTE" | ||||||
|  |   fi | ||||||
|  | } | ||||||
|  |  | ||||||
|  | push_changes() { | ||||||
|  |   log INFO "Pushing to $GIT_REMOTE" | ||||||
|  |   git push -u origin main | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # Show help if no arguments are given | ||||||
|  | # ======== | ||||||
|  | if [ $# -eq 0 ]; then | ||||||
|  |   echo "GITEA_API_TOKEN=<your token>" | ||||||
|  |   echo "Usage: $0 [--private] [--debug] [--message \"your commit message\"] <host_group>" | ||||||
|  |   echo "Example: $0 server" | ||||||
|  |   echo "         $0 --private workstation" | ||||||
|  |   echo "         $0 --debug server" | ||||||
|  |   echo "         $0 --message \"minor update\" server" | ||||||
|  |   echo | ||||||
|  |   echo "Note: You must cd into the target folder before running this script." | ||||||
|  |   echo "For example:" | ||||||
|  |   echo "  cd /etc && $0 server" | ||||||
|  |   echo | ||||||
|  |   echo "Authentication:" | ||||||
|  |   echo "  Git uses ~/.netrc for authentication. You can create it like this:" | ||||||
|  |   echo "  echo \"machine \$(echo \"$GITEA_URL\" | sed 's|https\\?://||') login $GITEA_USER password \"<password>\"\" > ~/.netrc" | ||||||
|  |   echo "  chmod 600 ~/.netrc" | ||||||
|  |   exit 0 | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | # Parse arguments | ||||||
|  | # ======== | ||||||
|  | POSITIONAL_ARGS=() | ||||||
|  | while [[ $# -gt 0 ]]; do | ||||||
|  |   case "$1" in | ||||||
|  |     --private) | ||||||
|  |       PRIVATE=true | ||||||
|  |       shift | ||||||
|  |       ;; | ||||||
|  |     --debug) | ||||||
|  |       DEBUG=true | ||||||
|  |       shift | ||||||
|  |       ;; | ||||||
|  |     --message) | ||||||
|  |       COMMIT_MESSAGE="$2" | ||||||
|  |       shift 2 | ||||||
|  |       ;; | ||||||
|  |     *) | ||||||
|  |       POSITIONAL_ARGS+=("$1") | ||||||
|  |       shift | ||||||
|  |       ;; | ||||||
|  |   esac | ||||||
|  | done | ||||||
|  |  | ||||||
|  | set -- "${POSITIONAL_ARGS[@]}" | ||||||
|  |  | ||||||
|  | if [ $# -ne 1 ]; then | ||||||
|  |   echo "Usage: $0 [--private] [--debug] [--message \"your commit message\"] <host_group>" | ||||||
|  |   exit 1 | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | HOST_GROUP=$(echo "$1" | tr '[:upper:]' '[:lower:]' | tr -cd 'a-z0-9-') | ||||||
|  | HOST_NAME=$(hostname -s | tr '[:upper:]' '[:lower:]' | tr -cd 'a-z0-9-') | ||||||
|  | FOLDER_NAME="${HOST_NAME}-$(basename "$PWD")" | ||||||
|  | REPO_PATH="$PWD" | ||||||
|  | REMOTE_PATH="$FOLDER_NAME" | ||||||
|  | GIT_REMOTE="$GITEA_URL/$GITEA_USER/$FOLDER_NAME.git" | ||||||
|  |  | ||||||
|  | # Git authentication hint | ||||||
|  | log DEBUG "Ensure ~/.netrc has: machine <host> login $GITEA_USER password <personal access token>" | ||||||
|  |  | ||||||
|  | # Check if GITEA_API_TOKEN is set | ||||||
|  | if [ -z "$GITEA_API_TOKEN" ]; then | ||||||
|  |   log WARNING "GITEA_API_TOKEN is not set. Skipping API repo creation." | ||||||
|  | else | ||||||
|  |   # Check if remote repo exists | ||||||
|  |   HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" \ | ||||||
|  |     -H "Authorization: token $GITEA_API_TOKEN" \ | ||||||
|  |     "$GITEA_API_URL/repos/$GITEA_USER/$FOLDER_NAME") | ||||||
|  |  | ||||||
|  |   if [ "$HTTP_STATUS" -ne 200 ]; then | ||||||
|  |     create_repo | ||||||
|  |   else | ||||||
|  |     log INFO "Remote repository already exists." | ||||||
|  |   fi | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | # Main Process | ||||||
|  | # ======== | ||||||
|  |  | ||||||
|  | # Safety check against pushing from / or $HOME | ||||||
|  | if [[ "$PWD" == "$HOME" || "$PWD" == "/" ]]; then | ||||||
|  |   log ERROR "Refusing to run inside \$PWD=$PWD" | ||||||
|  |   exit 1 | ||||||
|  | fi | ||||||
|  | log INFO "Pushing $REPO_PATH to $GIT_REMOTE" | ||||||
|  | cd "$REPO_PATH" || { log ERROR "Directory $REPO_PATH not found"; exit 1; } | ||||||
|  |  | ||||||
|  | # Initialize git if needed | ||||||
|  | # Branch is fixed to 'main' for simplicity and consistency | ||||||
|  | if [ ! -d .git ]; then | ||||||
|  |   log INFO "Initializing Git repo" | ||||||
|  |   git init | ||||||
|  |   git config init.defaultBranch main | ||||||
|  |   git checkout -b main | ||||||
|  | else | ||||||
|  |   log DEBUG ".git directory already present" | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | # Ensure at least one commit exists | ||||||
|  | prepare_commit | ||||||
|  |  | ||||||
|  | # Set or update remote | ||||||
|  | if [ "$HTTP_STATUS" -eq 200 ]; then | ||||||
|  |   setup_remote | ||||||
|  | else | ||||||
|  |   log WARNING "Skipping remote setup – repository does not exist." | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | # Push to remote | ||||||
|  | if [ "$HTTP_STATUS" -eq 200 ]; then | ||||||
|  |   push_changes | ||||||
|  | else | ||||||
|  |   log WARNING "Skipping push – repository does not exist." | ||||||
|  | fi | ||||||
|  |  | ||||||
							
								
								
									
										42
									
								
								import_embeddings.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								import_embeddings.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,42 @@ | |||||||
|  | #!/usr/bin/env python3 | ||||||
|  | # Script Version: 0.6 | ||||||
|  | # Description: Import existing embeddings.json into Open WebUI's ChromaDB instance using the new client API | ||||||
|  |  | ||||||
|  | import os | ||||||
|  | import json | ||||||
|  | from chromadb import PersistentClient | ||||||
|  |  | ||||||
|  | # Use Open WebUI's active Chroma DB directory | ||||||
|  | CHROMA_DIR = "/srv/open-webui/backend/data/vector_db" | ||||||
|  | COLLECTION_NAME = "cds_docs" | ||||||
|  | EMBEDDING_FILE = "embeddings.json" | ||||||
|  | CONTENT_DIR = "content" | ||||||
|  |  | ||||||
|  | # Stop Open WebUI before running this script to avoid file lock issues | ||||||
|  | client = PersistentClient(path=CHROMA_DIR) | ||||||
|  | collection = client.get_or_create_collection(name=COLLECTION_NAME) | ||||||
|  |  | ||||||
|  | # Load existing embeddings | ||||||
|  | with open(EMBEDDING_FILE, "r") as f: | ||||||
|  |     embeddings_data = json.load(f) | ||||||
|  |  | ||||||
|  | imported_count = 0 | ||||||
|  |  | ||||||
|  | # Ingest each document | ||||||
|  | for filename, vector in embeddings_data.items(): | ||||||
|  |     filepath = os.path.join(CONTENT_DIR, filename) | ||||||
|  |     try: | ||||||
|  |         with open(filepath, "r", encoding="utf-8") as f: | ||||||
|  |             text = f.read().strip() | ||||||
|  |         collection.add( | ||||||
|  |             documents=[text], | ||||||
|  |             metadatas=[{"filename": filename}], | ||||||
|  |             ids=[filename], | ||||||
|  |             embeddings=[vector] | ||||||
|  |         ) | ||||||
|  |         imported_count += 1 | ||||||
|  |     except FileNotFoundError: | ||||||
|  |         print(f"[WARN] Skipping missing file: {filepath}") | ||||||
|  |  | ||||||
|  | print(f"✅ Embeddings successfully imported into Chroma: {imported_count} documents") | ||||||
|  |  | ||||||
							
								
								
									
										108
									
								
								lxc_create_container.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										108
									
								
								lxc_create_container.sh
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,108 @@ | |||||||
|  | #!/bin/bash | ||||||
|  | # ============================================================================= | ||||||
|  | # Script Name: lxc_create_container.sh | ||||||
|  | # Version: 1.1 | ||||||
|  | # Description: This script creates a new LXC container from a template, assigns | ||||||
|  | #              a unique MAC address, updates the hostname and /etc/hosts file, | ||||||
|  | #              and verifies internet access. | ||||||
|  | # ============================================================================= | ||||||
|  |  | ||||||
|  | # Prompt for the new container hostname | ||||||
|  | read -e -p "LXCHOSTNAME: " LXCHOSTNAME | ||||||
|  | export LXCHOSTNAME | ||||||
|  |  | ||||||
|  | # Check if the template container is running and stop it if necessary | ||||||
|  | if lxc-info -n template | grep -q 'RUNNING'; then | ||||||
|  |     echo "Stopping the template container..." | ||||||
|  |     if ! lxc-stop -n template; then | ||||||
|  |         echo "Failed to stop the template container." | ||||||
|  |         exit 1 | ||||||
|  |     fi | ||||||
|  | else | ||||||
|  |     echo "Template container is not running." | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | # Copy the template to create a new container with the given hostname | ||||||
|  | echo "Creating a new container with hostname: $LXCHOSTNAME..." | ||||||
|  | if ! lxc-copy -n template -N "$LXCHOSTNAME"; then | ||||||
|  |     echo "Failed to copy the template container." | ||||||
|  |     exit 1 | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | # Function to generate a unique MAC address | ||||||
|  | generate_unique_hwaddr() { | ||||||
|  |     local hwaddr | ||||||
|  |     local existing_hwaddrs | ||||||
|  |     while : ; do | ||||||
|  |         hwaddr=$(printf '00:16:3e:%02x:%02x:%02x\n' $((RANDOM%256)) $((RANDOM%256)) $((RANDOM%256))) | ||||||
|  |         existing_hwaddrs=$(grep "lxc.net.0.hwaddr" /var/lib/lxc/*/config | grep "$hwaddr") | ||||||
|  |         if [ -z "$existing_hwaddrs" ]; then | ||||||
|  |             # MAC address is unique | ||||||
|  |             echo "$hwaddr" | ||||||
|  |             return | ||||||
|  |         fi | ||||||
|  |     done | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # Generate a unique MAC address | ||||||
|  | NEW_HWADDR=$(generate_unique_hwaddr) | ||||||
|  |  | ||||||
|  | # Path to the LXC configuration file | ||||||
|  | CONFIG_FILE="/var/lib/lxc/$LXCHOSTNAME/config" | ||||||
|  |  | ||||||
|  | # Replace the existing hwaddr line | ||||||
|  | echo "Updating MAC address in $CONFIG_FILE to $NEW_HWADDR..." | ||||||
|  | if ! sed -i "/^lxc.net.0.hwaddr/c\lxc.net.0.hwaddr = $NEW_HWADDR" "$CONFIG_FILE"; then | ||||||
|  |     echo "Failed to update MAC address in $CONFIG_FILE." | ||||||
|  |     exit 1 | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | # Start the new container | ||||||
|  | echo "Starting the new container..." | ||||||
|  | if ! lxc-start -n "$LXCHOSTNAME"; then | ||||||
|  |     echo "Failed to start the container $LXCHOSTNAME." | ||||||
|  |     exit 1 | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | # Wait for the container to start | ||||||
|  | sleep 5 | ||||||
|  |  | ||||||
|  | # Change the hostname inside the container | ||||||
|  | echo "Changing the hostname inside the container..." | ||||||
|  | if ! lxc-attach -n "$LXCHOSTNAME" -- bash -c "echo '$LXCHOSTNAME' > /etc/hostname" || \ | ||||||
|  |    ! lxc-attach -n "$LXCHOSTNAME" -- hostname "$LXCHOSTNAME"; then | ||||||
|  |     echo "Failed to set the hostname inside the container." | ||||||
|  |     exit 1 | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | # Update /etc/hosts | ||||||
|  | echo "Updating /etc/hosts inside the container..." | ||||||
|  | if ! lxc-attach -n "$LXCHOSTNAME" -- bash -c "echo '127.0.0.1 $LXCHOSTNAME' >> /etc/hosts"; then | ||||||
|  |     echo "Failed to update /etc/hosts inside the container." | ||||||
|  |     exit 1 | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | # Ensure the container has internet access (optional) | ||||||
|  | echo "Checking internet connectivity inside the container..." | ||||||
|  | if ! lxc-attach -n "$LXCHOSTNAME" -- ping -c 4 google.com; then | ||||||
|  |     echo "Container $LXCHOSTNAME does not have internet access." | ||||||
|  | fi | ||||||
|  | echo | ||||||
|  |  | ||||||
|  | # Stop and restart the container | ||||||
|  | echo "Restarting the container..." | ||||||
|  | if ! lxc-stop -n "$LXCHOSTNAME" || ! lxc-start -n "$LXCHOSTNAME"; then | ||||||
|  |     echo "Failed to restart the container $LXCHOSTNAME." | ||||||
|  |     exit 1 | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | # Display the MAC addresses to verify the changes | ||||||
|  | echo "Displaying the MAC addresses to verify the changes..." | ||||||
|  | grep lxc.net.0.hwaddr /var/lib/lxc/*/config | ||||||
|  |  | ||||||
|  | # Wait and list containers to ensure they are running | ||||||
|  | sleep 9 | ||||||
|  | echo "Listing all containers..." | ||||||
|  | lxc-ls -f | ||||||
|  |  | ||||||
|  | echo "LXC container setup completed successfully." | ||||||
							
								
								
									
										82
									
								
								lxc_list_login.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										82
									
								
								lxc_list_login.sh
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,82 @@ | |||||||
|  | #!/bin/bash | ||||||
|  | # ============================================================================= | ||||||
|  | # Script Name: lxc_list_login.sh | ||||||
|  | # Version: 03 | ||||||
|  | # Description: Lists LXC containers, checks their statuses, and allows login. | ||||||
|  | # ============================================================================= | ||||||
|  |  | ||||||
|  | # Required commands | ||||||
|  | REQUIRED_CMDS=("lxc-ls" "lxc-info" "lxc-start" "lxc-attach") | ||||||
|  |  | ||||||
|  | # Check if required commands are available | ||||||
|  | for CMD in "${REQUIRED_CMDS[@]}"; do | ||||||
|  |     if ! command -v "$CMD" &> /dev/null; then | ||||||
|  |         echo "The command $CMD is not installed. Please install it and try again." | ||||||
|  |         exit 1 | ||||||
|  |     fi | ||||||
|  | done | ||||||
|  |  | ||||||
|  | # List and check LXC containers | ||||||
|  | echo "List of all LXC containers:" | ||||||
|  | CONTAINERS=($(lxc-ls -f | awk 'NR>1 && $1 != "" {print $1}')) | ||||||
|  |  | ||||||
|  | # Check if there are any containers | ||||||
|  | if [[ ${#CONTAINERS[@]} -eq 0 ]]; then | ||||||
|  |     echo "There are no LXC containers." | ||||||
|  |     exit 1 | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | # Display containers and their status | ||||||
|  | printf "\n%-5s %-20s %-10s\n" "Index" "Container Name" "Status" | ||||||
|  | echo "------------------------------------------" | ||||||
|  | for (( I=0; I<${#CONTAINERS[@]}; I++ )); do | ||||||
|  |     LXCHOSTNAME="${CONTAINERS[$I]}" | ||||||
|  |     if [[ -n "$LXCHOSTNAME" ]]; then | ||||||
|  |         STATUS=$(lxc-info --name="$LXCHOSTNAME" | grep "State" | awk '{print $2}') | ||||||
|  |         printf "%-5d %-20s %-10s\n" "$I" "$LXCHOSTNAME" "$STATUS" | ||||||
|  |     fi | ||||||
|  | done | ||||||
|  |  | ||||||
|  | # Prompt user to select a container | ||||||
|  | read -p "Select a container to log in (0-$(( ${#CONTAINERS[@]} - 1 ))): " SELECTION | ||||||
|  |  | ||||||
|  | # Validate selection | ||||||
|  | if [[ $SELECTION =~ ^[0-9]+$ ]] && [[ $SELECTION -ge 0 && $SELECTION -lt ${#CONTAINERS[@]} ]]; then | ||||||
|  |     LXCHOSTNAME="${CONTAINERS[$SELECTION]}" | ||||||
|  |     STATUS=$(lxc-info --name="$LXCHOSTNAME" | grep "State" | awk '{print $2}') | ||||||
|  |      | ||||||
|  |     if [[ $STATUS == "STOPPED" ]]; then | ||||||
|  |         read -p "Container $LXCHOSTNAME is stopped. Do you want to start it? (y/n) " START_SELECTION | ||||||
|  |         if [[ $START_SELECTION == "y" ]]; then | ||||||
|  |             echo "Starting the container $LXCHOSTNAME..." | ||||||
|  |             if lxc-start --name="$LXCHOSTNAME"; then | ||||||
|  |                 echo "Container $LXCHOSTNAME has been started." | ||||||
|  |                 for i in {1..10}; do | ||||||
|  |                     STATUS=$(lxc-info --name="$LXCHOSTNAME" | grep "State" | awk '{print $2}') | ||||||
|  |                     if [[ $STATUS == "RUNNING" ]]; then | ||||||
|  |                         break | ||||||
|  |                     fi | ||||||
|  |                     sleep 1 | ||||||
|  |                 done | ||||||
|  |                 if [[ $STATUS != "RUNNING" ]]; then | ||||||
|  |                     echo "Container $LXCHOSTNAME failed to start within the timeout period." | ||||||
|  |                     exit 1 | ||||||
|  |                 fi | ||||||
|  |             else | ||||||
|  |                 echo "Error starting the container $LXCHOSTNAME." | ||||||
|  |                 exit 1 | ||||||
|  |             fi | ||||||
|  |         else | ||||||
|  |             echo "Container $LXCHOSTNAME was not started." | ||||||
|  |             exit 1 | ||||||
|  |         fi | ||||||
|  |     fi | ||||||
|  |     echo "Logging into the container $LXCHOSTNAME..." | ||||||
|  |     if ! lxc-attach --name="$LXCHOSTNAME"; then | ||||||
|  |         echo "Error logging into the container $LXCHOSTNAME." | ||||||
|  |         exit 1 | ||||||
|  |     fi | ||||||
|  | else | ||||||
|  |     echo "Invalid selection. Please run the script again and choose a valid number." | ||||||
|  |     exit 1 | ||||||
|  | fi | ||||||
							
								
								
									
										11
									
								
								raw_training_data.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								raw_training_data.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | |||||||
|  | import os | ||||||
|  |  | ||||||
|  | content_dir = "./content" | ||||||
|  | output_file = "raw_training_data.txt" | ||||||
|  |  | ||||||
|  | with open(output_file, "w", encoding="utf-8") as f: | ||||||
|  |     for txt_file in os.listdir(content_dir): | ||||||
|  |         if txt_file.endswith(".txt"): | ||||||
|  |             with open(os.path.join(content_dir, txt_file), "r", encoding="utf-8") as tf: | ||||||
|  |                 text = tf.read().strip() | ||||||
|  |                 f.write(text + "\n")  # One text per line | ||||||
							
								
								
									
										189
									
								
								scraper.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										189
									
								
								scraper.sh
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,189 @@ | |||||||
|  | #!/bin/bash | ||||||
|  | # Script Version: 01.8 | ||||||
|  | # Description: Scrapes and extracts page text from MediaWiki pages, cleans image artifacts, and deletes empty results | ||||||
|  |  | ||||||
|  | # Constants | ||||||
|  | DOWNLOAD_TIMEOUT=10 | ||||||
|  | TEXT_FILE_SUFFIX=".txt" | ||||||
|  | LINK_FILE_SUFFIX=".txt" | ||||||
|  |  | ||||||
|  | # Function to convert relative URLs to absolute URLs | ||||||
|  | resolve_url() { | ||||||
|  |     local base_url=$1 | ||||||
|  |     local relative_url=$2 | ||||||
|  |  | ||||||
|  |     if [[ "$relative_url" =~ ^https?:// ]]; then | ||||||
|  |         echo "$relative_url" | ||||||
|  |     elif [[ "$relative_url" =~ ^/ ]]; then | ||||||
|  |         echo "${base_url}${relative_url}" | ||||||
|  |     else | ||||||
|  |         echo "${base_url}/${relative_url}" | ||||||
|  |     fi | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # Function to check if URL should be skipped | ||||||
|  | should_skip_url() { | ||||||
|  |     local url=$1 | ||||||
|  |     case "$url" in | ||||||
|  |         *"load.php"*|*"IE9fixes.css"*|*"favicon.ico"*|*"opensearch_desc.php"*|*"api.php?action="*|*"Special:RecentChanges"*|*"Special:UserLogin"*|*"Special:RequestAccount"*|*"Dioxipedia:Privacy_policy"*|*"javascript:print();"*|*"mediawiki.org"*) | ||||||
|  |             return 0 ;;  # true, should skip | ||||||
|  |         *) | ||||||
|  |             return 1 ;;  # false, don't skip | ||||||
|  |     esac | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # Function to download content into a variable with timeout and error checking | ||||||
|  | download_content() { | ||||||
|  |     local url=$1 | ||||||
|  |     local exclude_file=$2 | ||||||
|  |  | ||||||
|  |     if should_skip_url "$url"; then | ||||||
|  |         echo "Skipping known irrelevant URL: $url" | ||||||
|  |         return 1 | ||||||
|  |     fi | ||||||
|  |  | ||||||
|  |     if [ -f "$exclude_file" ] && grep -Fx "$url" "$exclude_file" > /dev/null; then | ||||||
|  |         echo "Skipping excluded URL: $url" | ||||||
|  |         return 1 | ||||||
|  |     fi | ||||||
|  |  | ||||||
|  |     echo "Downloading: $url" | ||||||
|  |     SITECACHE=$(wget -T "$DOWNLOAD_TIMEOUT" -q -O - "$url" 2>/dev/null) | ||||||
|  |     if [ $? -ne 0 ] || [ -z "$SITECACHE" ]; then | ||||||
|  |         echo -e "\033[31m[ ERROR ]:\033[0m Failed to download $url" >&2 | ||||||
|  |         echo "$url" >> "$exclude_file" | ||||||
|  |         return 1 | ||||||
|  |     fi | ||||||
|  |     if ! echo "$SITECACHE" | grep -q "<html"; then | ||||||
|  |         echo "Skipping: $url (not HTML)" | ||||||
|  |         echo "$url" >> "$exclude_file" | ||||||
|  |         return 1 | ||||||
|  |     fi | ||||||
|  |     sleep 1 | ||||||
|  |     echo "Successfully downloaded: $url" | ||||||
|  |     return 0 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # Improved extraction function using pup and lynx | ||||||
|  | extract_text() { | ||||||
|  |     local output_file=$1 | ||||||
|  |     local url=$2 | ||||||
|  |     local exclude_file=$3 | ||||||
|  |  | ||||||
|  |     echo "Extracting text from SITECACHE to $output_file" | ||||||
|  |  | ||||||
|  |     EXTRACTED=$(echo "$SITECACHE" | pup '#mw-content-text' 2>/dev/null) | ||||||
|  |  | ||||||
|  |     if [ -z "$(echo "$EXTRACTED" | sed '/^\s*$/d')" ]; then | ||||||
|  |         echo "INFO: Content empty with #mw-content-text, trying #bodyContent" | ||||||
|  |         EXTRACTED=$(echo "$SITECACHE" | pup '#bodyContent' 2>/dev/null) | ||||||
|  |     fi | ||||||
|  |  | ||||||
|  |     if [ -z "$(echo "$EXTRACTED" | sed '/^\s*$/d')" ]; then | ||||||
|  |         echo "WARNING: Still no content after both selectors." | ||||||
|  |         echo "$url" >> "$exclude_file" | ||||||
|  |         return 1 | ||||||
|  |     fi | ||||||
|  |  | ||||||
|  |     echo "$EXTRACTED" | lynx -stdin -dump -nolist > "$output_file" | ||||||
|  |  | ||||||
|  |     if [ ! -s "$output_file" ]; then | ||||||
|  |         echo "WARNING: No text extracted from $url after lynx" | ||||||
|  |         echo "$url" >> "$exclude_file" | ||||||
|  |         rm -f "$output_file" | ||||||
|  |         return 1 | ||||||
|  |     fi | ||||||
|  |  | ||||||
|  |     # Remove lines containing image artifacts like [something.jpg] or [something.png] | ||||||
|  |     sed -i '/\[.*\(jpg\|jpeg\|png\).*]/Id' "$output_file" | ||||||
|  |  | ||||||
|  |     # Delete if file is smaller than 100 bytes | ||||||
|  |     if [ $(stat -c%s "$output_file") -lt 100 ]; then | ||||||
|  |         echo "INFO: Deleted $output_file (under 100 bytes)" | ||||||
|  |         rm -f "$output_file" | ||||||
|  |         echo "$url" >> "$exclude_file" | ||||||
|  |         return 1 | ||||||
|  |     fi | ||||||
|  |  | ||||||
|  |     echo "Successfully extracted text to $output_file" | ||||||
|  |     return 0 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # Function to extract page title | ||||||
|  | extract_title() { | ||||||
|  |     echo "$SITECACHE" | grep -oP '(?<=<title>).*(?=</title>)' | head -n 1 | sed 's/ - dioxipedia$//' | sed 's/[^a-zA-Z0-9-]/_/g' | sed 's/__*/_/g' | sed 's/^_//;s/_$//' | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # Function to extract links | ||||||
|  | extract_links() { | ||||||
|  |     local output_file=$1 | ||||||
|  |  | ||||||
|  |     echo "$SITECACHE" | grep -oP '(?<=href=")[^"]+' | grep -v 'translate\.goog' > "$output_file" | ||||||
|  |     if [ $? -ne 0 ] || [ ! -s "$output_file" ]; then | ||||||
|  |         echo "WARNING: No links extracted" | ||||||
|  |         rm -f "$output_file" | ||||||
|  |         return 1 | ||||||
|  |     fi | ||||||
|  |     echo "Successfully extracted links to $output_file" | ||||||
|  |     return 0 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # Main script logic | ||||||
|  | if [ $# -ne 1 ]; then | ||||||
|  |     echo "Usage: $0 <URL>" >&2 | ||||||
|  |     exit 1 | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | INITIAL_URL=$1 | ||||||
|  | DOMAIN=$(echo "$INITIAL_URL" | awk -F[/:] '{print $4}') | ||||||
|  | BASE_URL="https://$DOMAIN" | ||||||
|  | ALL_PAGES_URL="$BASE_URL/index.php?title=Special:AllPages" | ||||||
|  | LINKSFILE="$DOMAIN/links$LINK_FILE_SUFFIX" | ||||||
|  | EXCLUDE_FILE="$DOMAIN/exclude.txt" | ||||||
|  | CONTENT_DIR="$DOMAIN/content" | ||||||
|  |  | ||||||
|  | mkdir -p "$DOMAIN" | ||||||
|  | mkdir -p "$CONTENT_DIR" | ||||||
|  |  | ||||||
|  | # Step 1: Collect links | ||||||
|  | if ! download_content "$ALL_PAGES_URL" "$EXCLUDE_FILE"; then | ||||||
|  |     echo "Failed to download $ALL_PAGES_URL" | ||||||
|  |     exit 1 | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | if ! extract_links "$LINKSFILE"; then | ||||||
|  |     echo "Failed to extract links" | ||||||
|  |     exit 1 | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | # Step 2: Process links | ||||||
|  | PROCESSED_URLS=() | ||||||
|  | while IFS= read -r link; do | ||||||
|  |     URL=$(resolve_url "$BASE_URL" "$link") | ||||||
|  |  | ||||||
|  |     if [[ " ${PROCESSED_URLS[*]} " =~ " $URL " ]]; then | ||||||
|  |         echo "Skipping processed URL: $URL" | ||||||
|  |         continue | ||||||
|  |     fi | ||||||
|  |  | ||||||
|  |     if ! download_content "$URL" "$EXCLUDE_FILE"; then | ||||||
|  |         PROCESSED_URLS+=("$URL") | ||||||
|  |         continue | ||||||
|  |     fi | ||||||
|  |  | ||||||
|  |     PAGENAME=$(extract_title) | ||||||
|  |     [ -z "$PAGENAME" ] && PAGENAME="page" | ||||||
|  |  | ||||||
|  |     TEXTFILE="$CONTENT_DIR/$PAGENAME$TEXT_FILE_SUFFIX" | ||||||
|  |  | ||||||
|  |     if ! extract_text "$TEXTFILE" "$URL" "$EXCLUDE_FILE"; then | ||||||
|  |         PROCESSED_URLS+=("$URL") | ||||||
|  |         continue | ||||||
|  |     fi | ||||||
|  |  | ||||||
|  |     PROCESSED_URLS+=("$URL") | ||||||
|  | done < "$LINKSFILE" | ||||||
|  |  | ||||||
|  | echo "Processing complete." | ||||||
|  | exit 0 | ||||||
|  |  | ||||||
							
								
								
									
										47
									
								
								sendmail_test.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										47
									
								
								sendmail_test.sh
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,47 @@ | |||||||
|  | #!/bin/bash | ||||||
|  | # Script Name: sendmail_test.sh | ||||||
|  | # Version: 03 | ||||||
|  | # Description: This script sends a test email using sendmail. The recipient's email address is the first argument. | ||||||
|  | #              It logs messages to the console only. | ||||||
|  |  | ||||||
|  | # Check if an argument (email address) is provided | ||||||
|  | if [ -z "$1" ]; then | ||||||
|  |     TO="root" | ||||||
|  | else | ||||||
|  |     TO="$1" | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | # Email details | ||||||
|  | SUBJECT="Postfix Test" | ||||||
|  | FROM="$(whoami)@$(hostname)" | ||||||
|  | BODY="This is the email body!" | ||||||
|  |  | ||||||
|  | # Function to send email | ||||||
|  | send_email() { | ||||||
|  |     if ! command -v sendmail &> /dev/null; then | ||||||
|  |         echo "Sendmail is not installed or configured. Please ensure sendmail is installed and properly set up." >&2 | ||||||
|  |         exit 1 | ||||||
|  |     fi | ||||||
|  |  | ||||||
|  |     sendmail -t <<EOF | ||||||
|  | To: $TO | ||||||
|  | Subject: $SUBJECT | ||||||
|  | From: $FROM | ||||||
|  |  | ||||||
|  | $BODY | ||||||
|  | EOF | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # Function to log messages | ||||||
|  | log_message() { | ||||||
|  |     MESSAGE=$1 | ||||||
|  |     echo "$(date '+%Y-%m-%d %H:%M:%S') - $MESSAGE" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # Send email and log the result | ||||||
|  | log_message "Starting email send process." | ||||||
|  | if send_email; then | ||||||
|  |     log_message "Email sent successfully to $TO." | ||||||
|  | else | ||||||
|  |     log_message "Failed to send email to $TO." | ||||||
|  | fi | ||||||
							
								
								
									
										34
									
								
								update_openwebui_repo.zsh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										34
									
								
								update_openwebui_repo.zsh
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,34 @@ | |||||||
|  | #!/bin/zsh | ||||||
|  | # Script Version: 0.5 | ||||||
|  | # Description: Aktualisiert das Open WebUI Repository und startet den Dienst neu | ||||||
|  |  | ||||||
|  | cd /srv/open-webui || exit 1 | ||||||
|  |  | ||||||
|  | echo "[DEBUG] Working directory: $(pwd)" | ||||||
|  |  | ||||||
|  | # Sicherung nicht übergebener Änderungen | ||||||
|  | if [[ -n $(git status --porcelain) ]]; then | ||||||
|  |   echo "[DEBUG] Änderungen vorhanden – stash wird ausgeführt" | ||||||
|  |   git stash --all | ||||||
|  | else | ||||||
|  |   echo "[DEBUG] Keine lokalen Änderungen" | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | # Repository synchronisieren | ||||||
|  | echo "[DEBUG] Repository wird aktualisiert" | ||||||
|  | git pull --rebase | ||||||
|  |  | ||||||
|  | # Änderungen zurückholen, falls gestasht | ||||||
|  | if git stash list | grep -q "WIP on"; then | ||||||
|  |   echo "[DEBUG] Änderungen werden wiederhergestellt" | ||||||
|  |   git stash pop | ||||||
|  | else | ||||||
|  |   echo "[DEBUG] Keine Änderungen zum Wiederherstellen" | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | # Dienst neu starten und Status prüfen | ||||||
|  | systemctl restart openwebui.service | ||||||
|  | sleep 2 | ||||||
|  | echo "[DEBUG] openwebui.service wurde erfolgreich neu gestartet" | ||||||
|  | systemctl status openwebui.service --no-pager | ||||||
|  |  | ||||||
							
								
								
									
										104
									
								
								update_zone.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										104
									
								
								update_zone.sh
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,104 @@ | |||||||
|  | #!/bin/zsh | ||||||
|  | # Script Version: 10.6 | ||||||
|  | # Description: Dyn DNS update script, checks token, compares IPs, and updates DNS zone if needed. | ||||||
|  |  | ||||||
|  | # Set variables | ||||||
|  | # ======== | ||||||
|  | TOKEN_FILE="~/.dynProxy_token" | ||||||
|  | IP_FILE="~/.ip.txt" | ||||||
|  | UPDATE_URL="http://ip.dynproxy.net/update_zone" | ||||||
|  | LOG_FILE="/var/log/update_zone.log" | ||||||
|  |  | ||||||
|  | # Detect if script is running interactively | ||||||
|  | if [[ -t 1 ]]; then | ||||||
|  |     INTERACTIVE=true | ||||||
|  | else | ||||||
|  |     INTERACTIVE=false | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | # Functions | ||||||
|  | # ======== | ||||||
|  | log() { | ||||||
|  |     print "$(date '+%Y-%m-%dT%H:%M:%S.%6N'): $1" >> "$LOG_FILE" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | info() { | ||||||
|  |     if [[ "$INTERACTIVE" = true ]]; then | ||||||
|  |         echo "$1" | ||||||
|  |     fi | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # Output FastCGI headers if applicable | ||||||
|  | if [ -t 0 ]; then | ||||||
|  |     echo "Content-Type: text/plain" | ||||||
|  |     echo "" | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | # Ensure the token file exists | ||||||
|  | if [ ! -f "$TOKEN_FILE" ]; then | ||||||
|  |     log "ERROR: Token file not found." | ||||||
|  |     exit 1 | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | # Read the token | ||||||
|  | TOKEN=$(< "$TOKEN_FILE") | ||||||
|  | if [ -z "$TOKEN" ]; then | ||||||
|  |     log "ERROR: Token is empty." | ||||||
|  |     exit 1 | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | # Log the token retrieval | ||||||
|  | log "INFO: Token retrieved for update." | ||||||
|  |  | ||||||
|  | # Fetch the current public IP from the external service | ||||||
|  | IP_CURL=$(curl -s http://ip.dynproxy.net) | ||||||
|  | if [ -z "$IP_CURL" ]; then | ||||||
|  |     log "ERROR: Failed to fetch current public IP." | ||||||
|  |     exit 1 | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | # Ensure the IP file exists | ||||||
|  | if [ ! -f "$IP_FILE" ]; then | ||||||
|  |     log "INFO: IP file not found. Creating a new one with current IP." | ||||||
|  |     echo "$IP_CURL" > "$IP_FILE" | ||||||
|  |     log "INFO: IP file created with initial IP $IP_CURL." | ||||||
|  |     info "Initial IP file created with IP: $IP_CURL" | ||||||
|  |     PREVIOUS_IP="" # Set to empty to force update logic | ||||||
|  | else | ||||||
|  |     # Read the previous IP from the IP file | ||||||
|  |     PREVIOUS_IP=$(< "$IP_FILE") | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | # Compare the current IP with the previous IP | ||||||
|  | if [ "$IP_CURL" != "$PREVIOUS_IP" ]; then | ||||||
|  |     log "INFO: IP has changed from $PREVIOUS_IP to $IP_CURL. Proceeding with DNS update." | ||||||
|  |  | ||||||
|  |     # Log the IP to be updated | ||||||
|  |     log "INFO: Updating DNS for IP $IP_CURL." | ||||||
|  |  | ||||||
|  |     # Post the token and IP to trigger the DNS zone update | ||||||
|  |     RESPONSE=$(curl -s -o /tmp/curl_output -w "%{http_code}" -X POST \ | ||||||
|  |                    -H "Content-Type: application/x-www-form-urlencoded" \ | ||||||
|  |                    --data-urlencode "token=$TOKEN" \ | ||||||
|  |                    --data-urlencode "ip=$IP_CURL" \ | ||||||
|  |                    $UPDATE_URL) | ||||||
|  |  | ||||||
|  |     # Log the response and result | ||||||
|  |     if [ "$RESPONSE" -eq 200 ]; then | ||||||
|  |         log "SUCCESS: DNS zone update triggered successfully for token $TOKEN and IP $IP_CURL." | ||||||
|  |         info "DNS zone update triggered successfully" | ||||||
|  |         # Write the new IP to the IP file | ||||||
|  |         echo "$IP_CURL" > "$IP_FILE" | ||||||
|  |     else | ||||||
|  |         log "ERROR: Failed to trigger DNS zone update for token $TOKEN and IP $IP_CURL. Response code: $RESPONSE. Response body: $(cat /tmp/curl_output)" | ||||||
|  |         info "Failed to trigger DNS zone update. HTTP response: $RESPONSE" | ||||||
|  |         exit 1 | ||||||
|  |     fi | ||||||
|  | else | ||||||
|  |     log "INFO: IP has not changed. No update needed." | ||||||
|  |     info "IP has not changed. No update needed." | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | # Cleanup temporary files | ||||||
|  | rm -f /tmp/curl_output | ||||||
|  |  | ||||||
							
								
								
									
										43
									
								
								wrap_embeddings.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										43
									
								
								wrap_embeddings.sh
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,43 @@ | |||||||
|  | #!/bin/bash | ||||||
|  | # Script Version: 0.3 | ||||||
|  | # Description: Convert each .txt in content/ to .json with embedding in json/ | ||||||
|  |  | ||||||
|  | # Set variables | ||||||
|  | CONTENT_DIR="./content" | ||||||
|  | JSON_DIR="./json" | ||||||
|  | EMBEDDING_MODEL="sentence-transformers/all-MiniLM-L6-v2" | ||||||
|  |  | ||||||
|  | # Check dependencies | ||||||
|  | if ! python3 -c "import sentence_transformers" 2>/dev/null; then | ||||||
|  |   echo "[ERROR] ❌ sentence-transformers not installed. Run: pip3 install sentence-transformers" | ||||||
|  |   exit 1 | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | # Check input files | ||||||
|  | mkdir -p "$JSON_DIR" | ||||||
|  | if [ ! -d "$CONTENT_DIR" ] || ! ls "$CONTENT_DIR"/*.txt >/dev/null 2>&1; then | ||||||
|  |   echo "[ERROR] ❌ No .txt files found in $CONTENT_DIR" | ||||||
|  |   exit 1 | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | # Generate embeddings | ||||||
|  | python3 -c " | ||||||
|  | import sys, json, os | ||||||
|  | from sentence_transformers import SentenceTransformer | ||||||
|  | content_dir, json_dir = sys.argv[1], sys.argv[2] | ||||||
|  | model = SentenceTransformer('${EMBEDDING_MODEL}') | ||||||
|  | for txt_file in os.listdir(content_dir): | ||||||
|  |     if txt_file.endswith('.txt'): | ||||||
|  |         base_name = txt_file[:-4] | ||||||
|  |         try: | ||||||
|  |             with open(os.path.join(content_dir, txt_file), 'r', encoding='utf-8') as f: | ||||||
|  |                 text = f.read() | ||||||
|  |             embedding = model.encode([text])[0].tolist() | ||||||
|  |             with open(os.path.join(json_dir, f'{base_name}.json'), 'w') as f: | ||||||
|  |                 json.dump({'id': base_name, 'text': text, 'embedding': embedding}, f) | ||||||
|  |             print(f'[DEBUG] ✅ Saved: {json_dir}/{base_name}.json') | ||||||
|  |         except Exception as e: | ||||||
|  |             print(f'[ERROR] ❌ Failed: {txt_file} - {str(e)}', file=sys.stderr) | ||||||
|  | " "$CONTENT_DIR" "$JSON_DIR" 2>&1 | while read -r line; do echo "$line"; done | ||||||
|  |  | ||||||
|  | echo "✅ All .txt files converted to JSON with embeddings in $JSON_DIR" | ||||||
		Reference in New Issue
	
	Block a user