Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 32 additions & 17 deletions koyeb/lib/common.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -23,37 +23,36 @@ fi
# Koyeb specific functions
# ============================================================

# Ensure Koyeb CLI is installed
ensure_koyeb_cli() {
if command -v koyeb &>/dev/null; then
log_info "Koyeb CLI available"
return 0
fi

log_step "Installing Koyeb CLI..."

# Detect OS and architecture
local os=""
local arch=""

# Detect OS name for binary downloads (darwin or linux)
# Outputs the OS name to stdout; returns 1 on unsupported OS
_koyeb_detect_os() {
case "$(uname -s)" in
Darwin) os="darwin" ;;
Linux) os="linux" ;;
Darwin) echo "darwin" ;;
Linux) echo "linux" ;;
*)
log_error "Unsupported operating system: $(uname -s)"
return 1
;;
esac
}

# Detect CPU architecture for binary downloads (amd64 or arm64)
# Outputs the arch name to stdout; returns 1 on unsupported architecture
_koyeb_detect_arch() {
case "$(uname -m)" in
x86_64|amd64) arch="amd64" ;;
arm64|aarch64) arch="arm64" ;;
x86_64|amd64) echo "amd64" ;;
arm64|aarch64) echo "arm64" ;;
*)
log_error "Unsupported architecture: $(uname -m)"
return 1
;;
esac
}

# Download and install the Koyeb CLI binary
# Usage: _koyeb_install_cli OS ARCH
_koyeb_install_cli() {
local os="$1" arch="$2"
local install_dir="$HOME/.koyeb/bin"
mkdir -p "$install_dir"

Expand All@@ -72,6 +71,22 @@ ensure_koyeb_cli() {
log_error "Koyeb CLI not found in PATH after installation"
return 1
fi
}

# Ensure Koyeb CLI is installed
ensure_koyeb_cli() {
if command -v koyeb &>/dev/null; then
log_info "Koyeb CLI available"
return 0
fi

log_step "Installing Koyeb CLI..."

local os arch
os=$(_koyeb_detect_os) || return 1
arch=$(_koyeb_detect_arch) || return 1

_koyeb_install_cli "$os" "$arch" || return 1

log_info "Koyeb CLI installed"
}
Expand Down
82 changes: 50 additions & 32 deletions webdock/lib/common.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -134,56 +134,74 @@ _wait_for_webdock_server() {
WEBDOCK_SERVER_IP "Server" "${max_attempts}"
}

# Fetch all SSH public key IDs from the Webdock account
# Returns: JSON array of key IDs (e.g., [1, 2, 3]) or "[]" if none
_webdock_get_public_key_ids() {
local response
response=$(webdock_api GET "/account/publicKeys")
echo "$response" | python3 -c "
import json, sys
data = json.loads(sys.stdin.read())
if isinstance(data, list):
ids = [k['id'] for k in data if 'id' in k]
else:
ids = []
print(json.dumps(ids))
" 2>/dev/null || echo "[]"
}

# Validate Webdock server creation inputs
# Usage: _webdock_validate_inputs LOCATION PROFILE IMAGE SLUG
_webdock_validate_inputs() {
validate_resource_name "$1" || { log_error "Invalid WEBDOCK_LOCATION"; return 1; }
validate_resource_name "$2" || { log_error "Invalid WEBDOCK_PROFILE"; return 1; }
validate_resource_name "$3" || { log_error "Invalid WEBDOCK_IMAGE"; return 1; }
validate_resource_name "$4" || { log_error "Invalid server slug"; return 1; }
}

# Extract server slug from creation response or report failure
# Sets: WEBDOCK_SERVER_SLUG on success
# Usage: _webdock_handle_create_response RESPONSE
_webdock_handle_create_response() {
local response="$1"
if echo "$response" | grep -q '"slug"'; then
WEBDOCK_SERVER_SLUG=$(_extract_json_field "$response" "d['slug']")
export WEBDOCK_SERVER_SLUG
log_info "Server created: slug=$WEBDOCK_SERVER_SLUG"
return 0
fi
log_error "Failed to create Webdock server"
log_error "API Error: $(extract_api_error_message "$response" "$response")"
log_warn "Common issues:"
log_warn " - Insufficient account balance"
log_warn " - Profile/location unavailable (try different WEBDOCK_PROFILE or WEBDOCK_LOCATION)"
log_warn " - Server limit reached"
log_warn " - Slug already in use"
log_warn "Check your dashboard: https://my.webdock.io/"
return 1
}

create_server() {
local name="$1"
local slug="${name}"
local location_id="${WEBDOCK_LOCATION:-fi}"
local profile_slug="${WEBDOCK_PROFILE:-webdockmicro}"
local image_slug="${WEBDOCK_IMAGE:-ubuntu2404}"

# Validate env var inputs to prevent injection into Python code
validate_resource_name "$location_id" || { log_error "Invalid WEBDOCK_LOCATION"; return 1; }
validate_resource_name "$profile_slug" || { log_error "Invalid WEBDOCK_PROFILE"; return 1; }
validate_resource_name "$image_slug" || { log_error "Invalid WEBDOCK_IMAGE"; return 1; }
validate_resource_name "$slug" || { log_error "Invalid server slug"; return 1; }
_webdock_validate_inputs "$location_id" "$profile_slug" "$image_slug" "$slug" || return 1

log_step "Creating Webdock server '$name' (profile: $profile_slug, location: $location_id)..."

# Get all SSH public key IDs
local public_keys_response
public_keys_response=$(webdock_api GET "/account/publicKeys")
local public_key_ids
public_key_ids=$(echo "$public_keys_response" | python3 -c "
import json, sys
data = json.loads(sys.stdin.read())
if isinstance(data, list):
ids = [k['id'] for k in data if 'id' in k]
else:
ids = []
print(json.dumps(ids))
" 2>/dev/null || echo "[]")
public_key_ids=$(_webdock_get_public_key_ids)

local body
body=$(_webdock_build_server_body "$name" "$slug" "$location_id" "$profile_slug" "$image_slug" "$public_key_ids")

local response
response=$(webdock_api POST "/servers" "$body")

if echo "$response" | grep -q '"slug"'; then
WEBDOCK_SERVER_SLUG=$(echo "$response" | python3 -c "import json,sys; print(json.loads(sys.stdin.read())['slug'])")
export WEBDOCK_SERVER_SLUG
log_info "Server created: slug=$WEBDOCK_SERVER_SLUG"
else
log_error "Failed to create Webdock server"
log_error "API Error: $(extract_api_error_message "$response" "$response")"
log_warn "Common issues:"
log_warn " - Insufficient account balance"
log_warn " - Profile/location unavailable (try different WEBDOCK_PROFILE or WEBDOCK_LOCATION)"
log_warn " - Server limit reached"
log_warn " - Slug already in use"
log_warn "Check your dashboard: https://my.webdock.io/"
return 1
fi
_webdock_handle_create_response "$response" || return 1

_wait_for_webdock_server "$WEBDOCK_SERVER_SLUG"
}
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 32 additions & 17 deletions koyeb/lib/common.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -23,37 +23,36 @@ fi
# Koyeb specific functions
# ============================================================

# Ensure Koyeb CLI is installed
ensure_koyeb_cli() {
if command -v koyeb &>/dev/null; then
log_info "Koyeb CLI available"
return 0
fi

log_step "Installing Koyeb CLI..."

# Detect OS and architecture
local os=""
local arch=""

# Detect OS name for binary downloads (darwin or linux)
# Outputs the OS name to stdout; returns 1 on unsupported OS
_koyeb_detect_os() {
case "$(uname -s)" in
Darwin) os="darwin" ;;
Linux) os="linux" ;;
Darwin) echo "darwin" ;;
Linux) echo "linux" ;;
*)
log_error "Unsupported operating system: $(uname -s)"
return 1
;;
esac
}

# Detect CPU architecture for binary downloads (amd64 or arm64)
# Outputs the arch name to stdout; returns 1 on unsupported architecture
_koyeb_detect_arch() {
case "$(uname -m)" in
x86_64|amd64) arch="amd64" ;;
arm64|aarch64) arch="arm64" ;;
x86_64|amd64) echo "amd64" ;;
arm64|aarch64) echo "arm64" ;;
*)
log_error "Unsupported architecture: $(uname -m)"
return 1
;;
esac
}

# Download and install the Koyeb CLI binary
# Usage: _koyeb_install_cli OS ARCH
_koyeb_install_cli() {
local os="$1" arch="$2"
local install_dir="$HOME/.koyeb/bin"
mkdir -p "$install_dir"

Expand All@@ -72,6 +71,22 @@ ensure_koyeb_cli() {
log_error "Koyeb CLI not found in PATH after installation"
return 1
fi
}

# Ensure Koyeb CLI is installed
ensure_koyeb_cli() {
if command -v koyeb &>/dev/null; then
log_info "Koyeb CLI available"
return 0
fi

log_step "Installing Koyeb CLI..."

local os arch
os=$(_koyeb_detect_os) || return 1
arch=$(_koyeb_detect_arch) || return 1

_koyeb_install_cli "$os" "$arch" || return 1

log_info "Koyeb CLI installed"
}
Expand Down
82 changes: 50 additions & 32 deletions webdock/lib/common.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -134,56 +134,74 @@ _wait_for_webdock_server() {
WEBDOCK_SERVER_IP "Server" "${max_attempts}"
}

# Fetch all SSH public key IDs from the Webdock account
# Returns: JSON array of key IDs (e.g., [1, 2, 3]) or "[]" if none
_webdock_get_public_key_ids() {
local response
response=$(webdock_api GET "/account/publicKeys")
echo "$response" | python3 -c "
import json, sys
data = json.loads(sys.stdin.read())
if isinstance(data, list):
ids = [k['id'] for k in data if 'id' in k]
else:
ids = []
print(json.dumps(ids))
" 2>/dev/null || echo "[]"
}

# Validate Webdock server creation inputs
# Usage: _webdock_validate_inputs LOCATION PROFILE IMAGE SLUG
_webdock_validate_inputs() {
validate_resource_name "$1" || { log_error "Invalid WEBDOCK_LOCATION"; return 1; }
validate_resource_name "$2" || { log_error "Invalid WEBDOCK_PROFILE"; return 1; }
validate_resource_name "$3" || { log_error "Invalid WEBDOCK_IMAGE"; return 1; }
validate_resource_name "$4" || { log_error "Invalid server slug"; return 1; }
}

# Extract server slug from creation response or report failure
# Sets: WEBDOCK_SERVER_SLUG on success
# Usage: _webdock_handle_create_response RESPONSE
_webdock_handle_create_response() {
local response="$1"
if echo "$response" | grep -q '"slug"'; then
WEBDOCK_SERVER_SLUG=$(_extract_json_field "$response" "d['slug']")
export WEBDOCK_SERVER_SLUG
log_info "Server created: slug=$WEBDOCK_SERVER_SLUG"
return 0
fi
log_error "Failed to create Webdock server"
log_error "API Error: $(extract_api_error_message "$response" "$response")"
log_warn "Common issues:"
log_warn " - Insufficient account balance"
log_warn " - Profile/location unavailable (try different WEBDOCK_PROFILE or WEBDOCK_LOCATION)"
log_warn " - Server limit reached"
log_warn " - Slug already in use"
log_warn "Check your dashboard: https://my.webdock.io/"
return 1
}

create_server() {
local name="$1"
local slug="${name}"
local location_id="${WEBDOCK_LOCATION:-fi}"
local profile_slug="${WEBDOCK_PROFILE:-webdockmicro}"
local image_slug="${WEBDOCK_IMAGE:-ubuntu2404}"

# Validate env var inputs to prevent injection into Python code
validate_resource_name "$location_id" || { log_error "Invalid WEBDOCK_LOCATION"; return 1; }
validate_resource_name "$profile_slug" || { log_error "Invalid WEBDOCK_PROFILE"; return 1; }
validate_resource_name "$image_slug" || { log_error "Invalid WEBDOCK_IMAGE"; return 1; }
validate_resource_name "$slug" || { log_error "Invalid server slug"; return 1; }
_webdock_validate_inputs "$location_id" "$profile_slug" "$image_slug" "$slug" || return 1

log_step "Creating Webdock server '$name' (profile: $profile_slug, location: $location_id)..."

# Get all SSH public key IDs
local public_keys_response
public_keys_response=$(webdock_api GET "/account/publicKeys")
local public_key_ids
public_key_ids=$(echo "$public_keys_response" | python3 -c "
import json, sys
data = json.loads(sys.stdin.read())
if isinstance(data, list):
ids = [k['id'] for k in data if 'id' in k]
else:
ids = []
print(json.dumps(ids))
" 2>/dev/null || echo "[]")
public_key_ids=$(_webdock_get_public_key_ids)

local body
body=$(_webdock_build_server_body "$name" "$slug" "$location_id" "$profile_slug" "$image_slug" "$public_key_ids")

local response
response=$(webdock_api POST "/servers" "$body")

if echo "$response" | grep -q '"slug"'; then
WEBDOCK_SERVER_SLUG=$(echo "$response" | python3 -c "import json,sys; print(json.loads(sys.stdin.read())['slug'])")
export WEBDOCK_SERVER_SLUG
log_info "Server created: slug=$WEBDOCK_SERVER_SLUG"
else
log_error "Failed to create Webdock server"
log_error "API Error: $(extract_api_error_message "$response" "$response")"
log_warn "Common issues:"
log_warn " - Insufficient account balance"
log_warn " - Profile/location unavailable (try different WEBDOCK_PROFILE or WEBDOCK_LOCATION)"
log_warn " - Server limit reached"
log_warn " - Slug already in use"
log_warn "Check your dashboard: https://my.webdock.io/"
return 1
fi
_webdock_handle_create_response "$response" || return 1

_wait_for_webdock_server "$WEBDOCK_SERVER_SLUG"
}
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 32 additions & 17 deletions koyeb/lib/common.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -23,37 +23,36 @@ fi
# Koyeb specific functions
# ============================================================

# Ensure Koyeb CLI is installed
ensure_koyeb_cli() {
if command -v koyeb &>/dev/null; then
log_info "Koyeb CLI available"
return 0
fi

log_step "Installing Koyeb CLI..."

# Detect OS and architecture
local os=""
local arch=""

# Detect OS name for binary downloads (darwin or linux)
# Outputs the OS name to stdout; returns 1 on unsupported OS
_koyeb_detect_os() {
case "$(uname -s)" in
Darwin) os="darwin" ;;
Linux) os="linux" ;;
Darwin) echo "darwin" ;;
Linux) echo "linux" ;;
*)
log_error "Unsupported operating system: $(uname -s)"
return 1
;;
esac
}

# Detect CPU architecture for binary downloads (amd64 or arm64)
# Outputs the arch name to stdout; returns 1 on unsupported architecture
_koyeb_detect_arch() {
case "$(uname -m)" in
x86_64|amd64) arch="amd64" ;;
arm64|aarch64) arch="arm64" ;;
x86_64|amd64) echo "amd64" ;;
arm64|aarch64) echo "arm64" ;;
*)
log_error "Unsupported architecture: $(uname -m)"
return 1
;;
esac
}

# Download and install the Koyeb CLI binary
# Usage: _koyeb_install_cli OS ARCH
_koyeb_install_cli() {
local os="$1" arch="$2"
local install_dir="$HOME/.koyeb/bin"
mkdir -p "$install_dir"

Expand All@@ -72,6 +71,22 @@ ensure_koyeb_cli() {
log_error "Koyeb CLI not found in PATH after installation"
return 1
fi
}

# Ensure Koyeb CLI is installed
ensure_koyeb_cli() {
if command -v koyeb &>/dev/null; then
log_info "Koyeb CLI available"
return 0
fi

log_step "Installing Koyeb CLI..."

local os arch
os=$(_koyeb_detect_os) || return 1
arch=$(_koyeb_detect_arch) || return 1

_koyeb_install_cli "$os" "$arch" || return 1

log_info "Koyeb CLI installed"
}
Expand Down
82 changes: 50 additions & 32 deletions webdock/lib/common.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -134,56 +134,74 @@ _wait_for_webdock_server() {
WEBDOCK_SERVER_IP "Server" "${max_attempts}"
}

# Fetch all SSH public key IDs from the Webdock account
# Returns: JSON array of key IDs (e.g., [1, 2, 3]) or "[]" if none
_webdock_get_public_key_ids() {
local response
response=$(webdock_api GET "/account/publicKeys")
echo "$response" | python3 -c "
import json, sys
data = json.loads(sys.stdin.read())
if isinstance(data, list):
ids = [k['id'] for k in data if 'id' in k]
else:
ids = []
print(json.dumps(ids))
" 2>/dev/null || echo "[]"
}

# Validate Webdock server creation inputs
# Usage: _webdock_validate_inputs LOCATION PROFILE IMAGE SLUG
_webdock_validate_inputs() {
validate_resource_name "$1" || { log_error "Invalid WEBDOCK_LOCATION"; return 1; }
validate_resource_name "$2" || { log_error "Invalid WEBDOCK_PROFILE"; return 1; }
validate_resource_name "$3" || { log_error "Invalid WEBDOCK_IMAGE"; return 1; }
validate_resource_name "$4" || { log_error "Invalid server slug"; return 1; }
}

# Extract server slug from creation response or report failure
# Sets: WEBDOCK_SERVER_SLUG on success
# Usage: _webdock_handle_create_response RESPONSE
_webdock_handle_create_response() {
local response="$1"
if echo "$response" | grep -q '"slug"'; then
WEBDOCK_SERVER_SLUG=$(_extract_json_field "$response" "d['slug']")
export WEBDOCK_SERVER_SLUG
log_info "Server created: slug=$WEBDOCK_SERVER_SLUG"
return 0
fi
log_error "Failed to create Webdock server"
log_error "API Error: $(extract_api_error_message "$response" "$response")"
log_warn "Common issues:"
log_warn " - Insufficient account balance"
log_warn " - Profile/location unavailable (try different WEBDOCK_PROFILE or WEBDOCK_LOCATION)"
log_warn " - Server limit reached"
log_warn " - Slug already in use"
log_warn "Check your dashboard: https://my.webdock.io/"
return 1
}

create_server() {
local name="$1"
local slug="${name}"
local location_id="${WEBDOCK_LOCATION:-fi}"
local profile_slug="${WEBDOCK_PROFILE:-webdockmicro}"
local image_slug="${WEBDOCK_IMAGE:-ubuntu2404}"

# Validate env var inputs to prevent injection into Python code
validate_resource_name "$location_id" || { log_error "Invalid WEBDOCK_LOCATION"; return 1; }
validate_resource_name "$profile_slug" || { log_error "Invalid WEBDOCK_PROFILE"; return 1; }
validate_resource_name "$image_slug" || { log_error "Invalid WEBDOCK_IMAGE"; return 1; }
validate_resource_name "$slug" || { log_error "Invalid server slug"; return 1; }
_webdock_validate_inputs "$location_id" "$profile_slug" "$image_slug" "$slug" || return 1

log_step "Creating Webdock server '$name' (profile: $profile_slug, location: $location_id)..."

# Get all SSH public key IDs
local public_keys_response
public_keys_response=$(webdock_api GET "/account/publicKeys")
local public_key_ids
public_key_ids=$(echo "$public_keys_response" | python3 -c "
import json, sys
data = json.loads(sys.stdin.read())
if isinstance(data, list):
ids = [k['id'] for k in data if 'id' in k]
else:
ids = []
print(json.dumps(ids))
" 2>/dev/null || echo "[]")
public_key_ids=$(_webdock_get_public_key_ids)

local body
body=$(_webdock_build_server_body "$name" "$slug" "$location_id" "$profile_slug" "$image_slug" "$public_key_ids")

local response
response=$(webdock_api POST "/servers" "$body")

if echo "$response" | grep -q '"slug"'; then
WEBDOCK_SERVER_SLUG=$(echo "$response" | python3 -c "import json,sys; print(json.loads(sys.stdin.read())['slug'])")
export WEBDOCK_SERVER_SLUG
log_info "Server created: slug=$WEBDOCK_SERVER_SLUG"
else
log_error "Failed to create Webdock server"
log_error "API Error: $(extract_api_error_message "$response" "$response")"
log_warn "Common issues:"
log_warn " - Insufficient account balance"
log_warn " - Profile/location unavailable (try different WEBDOCK_PROFILE or WEBDOCK_LOCATION)"
log_warn " - Server limit reached"
log_warn " - Slug already in use"
log_warn "Check your dashboard: https://my.webdock.io/"
return 1
fi
_webdock_handle_create_response "$response" || return 1

_wait_for_webdock_server "$WEBDOCK_SERVER_SLUG"
}
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 32 additions & 17 deletions koyeb/lib/common.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -23,37 +23,36 @@ fi
# Koyeb specific functions
# ============================================================

# Ensure Koyeb CLI is installed
ensure_koyeb_cli() {
if command -v koyeb &>/dev/null; then
log_info "Koyeb CLI available"
return 0
fi

log_step "Installing Koyeb CLI..."

# Detect OS and architecture
local os=""
local arch=""

# Detect OS name for binary downloads (darwin or linux)
# Outputs the OS name to stdout; returns 1 on unsupported OS
_koyeb_detect_os() {
case "$(uname -s)" in
Darwin) os="darwin" ;;
Linux) os="linux" ;;
Darwin) echo "darwin" ;;
Linux) echo "linux" ;;
*)
log_error "Unsupported operating system: $(uname -s)"
return 1
;;
esac
}

# Detect CPU architecture for binary downloads (amd64 or arm64)
# Outputs the arch name to stdout; returns 1 on unsupported architecture
_koyeb_detect_arch() {
case "$(uname -m)" in
x86_64|amd64) arch="amd64" ;;
arm64|aarch64) arch="arm64" ;;
x86_64|amd64) echo "amd64" ;;
arm64|aarch64) echo "arm64" ;;
*)
log_error "Unsupported architecture: $(uname -m)"
return 1
;;
esac
}

# Download and install the Koyeb CLI binary
# Usage: _koyeb_install_cli OS ARCH
_koyeb_install_cli() {
local os="$1" arch="$2"
local install_dir="$HOME/.koyeb/bin"
mkdir -p "$install_dir"

Expand All@@ -72,6 +71,22 @@ ensure_koyeb_cli() {
log_error "Koyeb CLI not found in PATH after installation"
return 1
fi
}

# Ensure Koyeb CLI is installed
ensure_koyeb_cli() {
if command -v koyeb &>/dev/null; then
log_info "Koyeb CLI available"
return 0
fi

log_step "Installing Koyeb CLI..."

local os arch
os=$(_koyeb_detect_os) || return 1
arch=$(_koyeb_detect_arch) || return 1

_koyeb_install_cli "$os" "$arch" || return 1

log_info "Koyeb CLI installed"
}
Expand Down
82 changes: 50 additions & 32 deletions webdock/lib/common.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -134,56 +134,74 @@ _wait_for_webdock_server() {
WEBDOCK_SERVER_IP "Server" "${max_attempts}"
}

# Fetch all SSH public key IDs from the Webdock account
# Returns: JSON array of key IDs (e.g., [1, 2, 3]) or "[]" if none
_webdock_get_public_key_ids() {
local response
response=$(webdock_api GET "/account/publicKeys")
echo "$response" | python3 -c "
import json, sys
data = json.loads(sys.stdin.read())
if isinstance(data, list):
ids = [k['id'] for k in data if 'id' in k]
else:
ids = []
print(json.dumps(ids))
" 2>/dev/null || echo "[]"
}

# Validate Webdock server creation inputs
# Usage: _webdock_validate_inputs LOCATION PROFILE IMAGE SLUG
_webdock_validate_inputs() {
validate_resource_name "$1" || { log_error "Invalid WEBDOCK_LOCATION"; return 1; }
validate_resource_name "$2" || { log_error "Invalid WEBDOCK_PROFILE"; return 1; }
validate_resource_name "$3" || { log_error "Invalid WEBDOCK_IMAGE"; return 1; }
validate_resource_name "$4" || { log_error "Invalid server slug"; return 1; }
}

# Extract server slug from creation response or report failure
# Sets: WEBDOCK_SERVER_SLUG on success
# Usage: _webdock_handle_create_response RESPONSE
_webdock_handle_create_response() {
local response="$1"
if echo "$response" | grep -q '"slug"'; then
WEBDOCK_SERVER_SLUG=$(_extract_json_field "$response" "d['slug']")
export WEBDOCK_SERVER_SLUG
log_info "Server created: slug=$WEBDOCK_SERVER_SLUG"
return 0
fi
log_error "Failed to create Webdock server"
log_error "API Error: $(extract_api_error_message "$response" "$response")"
log_warn "Common issues:"
log_warn " - Insufficient account balance"
log_warn " - Profile/location unavailable (try different WEBDOCK_PROFILE or WEBDOCK_LOCATION)"
log_warn " - Server limit reached"
log_warn " - Slug already in use"
log_warn "Check your dashboard: https://my.webdock.io/"
return 1
}

create_server() {
local name="$1"
local slug="${name}"
local location_id="${WEBDOCK_LOCATION:-fi}"
local profile_slug="${WEBDOCK_PROFILE:-webdockmicro}"
local image_slug="${WEBDOCK_IMAGE:-ubuntu2404}"

# Validate env var inputs to prevent injection into Python code
validate_resource_name "$location_id" || { log_error "Invalid WEBDOCK_LOCATION"; return 1; }
validate_resource_name "$profile_slug" || { log_error "Invalid WEBDOCK_PROFILE"; return 1; }
validate_resource_name "$image_slug" || { log_error "Invalid WEBDOCK_IMAGE"; return 1; }
validate_resource_name "$slug" || { log_error "Invalid server slug"; return 1; }
_webdock_validate_inputs "$location_id" "$profile_slug" "$image_slug" "$slug" || return 1

log_step "Creating Webdock server '$name' (profile: $profile_slug, location: $location_id)..."

# Get all SSH public key IDs
local public_keys_response
public_keys_response=$(webdock_api GET "/account/publicKeys")
local public_key_ids
public_key_ids=$(echo "$public_keys_response" | python3 -c "
import json, sys
data = json.loads(sys.stdin.read())
if isinstance(data, list):
ids = [k['id'] for k in data if 'id' in k]
else:
ids = []
print(json.dumps(ids))
" 2>/dev/null || echo "[]")
public_key_ids=$(_webdock_get_public_key_ids)

local body
body=$(_webdock_build_server_body "$name" "$slug" "$location_id" "$profile_slug" "$image_slug" "$public_key_ids")

local response
response=$(webdock_api POST "/servers" "$body")

if echo "$response" | grep -q '"slug"'; then
WEBDOCK_SERVER_SLUG=$(echo "$response" | python3 -c "import json,sys; print(json.loads(sys.stdin.read())['slug'])")
export WEBDOCK_SERVER_SLUG
log_info "Server created: slug=$WEBDOCK_SERVER_SLUG"
else
log_error "Failed to create Webdock server"
log_error "API Error: $(extract_api_error_message "$response" "$response")"
log_warn "Common issues:"
log_warn " - Insufficient account balance"
log_warn " - Profile/location unavailable (try different WEBDOCK_PROFILE or WEBDOCK_LOCATION)"
log_warn " - Server limit reached"
log_warn " - Slug already in use"
log_warn "Check your dashboard: https://my.webdock.io/"
return 1
fi
_webdock_handle_create_response "$response" || return 1

_wait_for_webdock_server "$WEBDOCK_SERVER_SLUG"
}
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 32 additions & 17 deletions koyeb/lib/common.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -23,37 +23,36 @@ fi
# Koyeb specific functions
# ============================================================

# Ensure Koyeb CLI is installed
ensure_koyeb_cli() {
if command -v koyeb &>/dev/null; then
log_info "Koyeb CLI available"
return 0
fi

log_step "Installing Koyeb CLI..."

# Detect OS and architecture
local os=""
local arch=""

# Detect OS name for binary downloads (darwin or linux)
# Outputs the OS name to stdout; returns 1 on unsupported OS
_koyeb_detect_os() {
case "$(uname -s)" in
Darwin) os="darwin" ;;
Linux) os="linux" ;;
Darwin) echo "darwin" ;;
Linux) echo "linux" ;;
*)
log_error "Unsupported operating system: $(uname -s)"
return 1
;;
esac
}

# Detect CPU architecture for binary downloads (amd64 or arm64)
# Outputs the arch name to stdout; returns 1 on unsupported architecture
_koyeb_detect_arch() {
case "$(uname -m)" in
x86_64|amd64) arch="amd64" ;;
arm64|aarch64) arch="arm64" ;;
x86_64|amd64) echo "amd64" ;;
arm64|aarch64) echo "arm64" ;;
*)
log_error "Unsupported architecture: $(uname -m)"
return 1
;;
esac
}

# Download and install the Koyeb CLI binary
# Usage: _koyeb_install_cli OS ARCH
_koyeb_install_cli() {
local os="$1" arch="$2"
local install_dir="$HOME/.koyeb/bin"
mkdir -p "$install_dir"

Expand All@@ -72,6 +71,22 @@ ensure_koyeb_cli() {
log_error "Koyeb CLI not found in PATH after installation"
return 1
fi
}

# Ensure Koyeb CLI is installed
ensure_koyeb_cli() {
if command -v koyeb &>/dev/null; then
log_info "Koyeb CLI available"
return 0
fi

log_step "Installing Koyeb CLI..."

local os arch
os=$(_koyeb_detect_os) || return 1
arch=$(_koyeb_detect_arch) || return 1

_koyeb_install_cli "$os" "$arch" || return 1

log_info "Koyeb CLI installed"
}
Expand Down
82 changes: 50 additions & 32 deletions webdock/lib/common.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -134,56 +134,74 @@ _wait_for_webdock_server() {
WEBDOCK_SERVER_IP "Server" "${max_attempts}"
}

# Fetch all SSH public key IDs from the Webdock account
# Returns: JSON array of key IDs (e.g., [1, 2, 3]) or "[]" if none
_webdock_get_public_key_ids() {
local response
response=$(webdock_api GET "/account/publicKeys")
echo "$response" | python3 -c "
import json, sys
data = json.loads(sys.stdin.read())
if isinstance(data, list):
ids = [k['id'] for k in data if 'id' in k]
else:
ids = []
print(json.dumps(ids))
" 2>/dev/null || echo "[]"
}

# Validate Webdock server creation inputs
# Usage: _webdock_validate_inputs LOCATION PROFILE IMAGE SLUG
_webdock_validate_inputs() {
validate_resource_name "$1" || { log_error "Invalid WEBDOCK_LOCATION"; return 1; }
validate_resource_name "$2" || { log_error "Invalid WEBDOCK_PROFILE"; return 1; }
validate_resource_name "$3" || { log_error "Invalid WEBDOCK_IMAGE"; return 1; }
validate_resource_name "$4" || { log_error "Invalid server slug"; return 1; }
}

# Extract server slug from creation response or report failure
# Sets: WEBDOCK_SERVER_SLUG on success
# Usage: _webdock_handle_create_response RESPONSE
_webdock_handle_create_response() {
local response="$1"
if echo "$response" | grep -q '"slug"'; then
WEBDOCK_SERVER_SLUG=$(_extract_json_field "$response" "d['slug']")
export WEBDOCK_SERVER_SLUG
log_info "Server created: slug=$WEBDOCK_SERVER_SLUG"
return 0
fi
log_error "Failed to create Webdock server"
log_error "API Error: $(extract_api_error_message "$response" "$response")"
log_warn "Common issues:"
log_warn " - Insufficient account balance"
log_warn " - Profile/location unavailable (try different WEBDOCK_PROFILE or WEBDOCK_LOCATION)"
log_warn " - Server limit reached"
log_warn " - Slug already in use"
log_warn "Check your dashboard: https://my.webdock.io/"
return 1
}

create_server() {
local name="$1"
local slug="${name}"
local location_id="${WEBDOCK_LOCATION:-fi}"
local profile_slug="${WEBDOCK_PROFILE:-webdockmicro}"
local image_slug="${WEBDOCK_IMAGE:-ubuntu2404}"

# Validate env var inputs to prevent injection into Python code
validate_resource_name "$location_id" || { log_error "Invalid WEBDOCK_LOCATION"; return 1; }
validate_resource_name "$profile_slug" || { log_error "Invalid WEBDOCK_PROFILE"; return 1; }
validate_resource_name "$image_slug" || { log_error "Invalid WEBDOCK_IMAGE"; return 1; }
validate_resource_name "$slug" || { log_error "Invalid server slug"; return 1; }
_webdock_validate_inputs "$location_id" "$profile_slug" "$image_slug" "$slug" || return 1

log_step "Creating Webdock server '$name' (profile: $profile_slug, location: $location_id)..."

# Get all SSH public key IDs
local public_keys_response
public_keys_response=$(webdock_api GET "/account/publicKeys")
local public_key_ids
public_key_ids=$(echo "$public_keys_response" | python3 -c "
import json, sys
data = json.loads(sys.stdin.read())
if isinstance(data, list):
ids = [k['id'] for k in data if 'id' in k]
else:
ids = []
print(json.dumps(ids))
" 2>/dev/null || echo "[]")
public_key_ids=$(_webdock_get_public_key_ids)

local body
body=$(_webdock_build_server_body "$name" "$slug" "$location_id" "$profile_slug" "$image_slug" "$public_key_ids")

local response
response=$(webdock_api POST "/servers" "$body")

if echo "$response" | grep -q '"slug"'; then
WEBDOCK_SERVER_SLUG=$(echo "$response" | python3 -c "import json,sys; print(json.loads(sys.stdin.read())['slug'])")
export WEBDOCK_SERVER_SLUG
log_info "Server created: slug=$WEBDOCK_SERVER_SLUG"
else
log_error "Failed to create Webdock server"
log_error "API Error: $(extract_api_error_message "$response" "$response")"
log_warn "Common issues:"
log_warn " - Insufficient account balance"
log_warn " - Profile/location unavailable (try different WEBDOCK_PROFILE or WEBDOCK_LOCATION)"
log_warn " - Server limit reached"
log_warn " - Slug already in use"
log_warn "Check your dashboard: https://my.webdock.io/"
return 1
fi
_webdock_handle_create_response "$response" || return 1

_wait_for_webdock_server "$WEBDOCK_SERVER_SLUG"
}
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 32 additions & 17 deletions koyeb/lib/common.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -23,37 +23,36 @@ fi
# Koyeb specific functions
# ============================================================

# Ensure Koyeb CLI is installed
ensure_koyeb_cli() {
if command -v koyeb &>/dev/null; then
log_info "Koyeb CLI available"
return 0
fi

log_step "Installing Koyeb CLI..."

# Detect OS and architecture
local os=""
local arch=""

# Detect OS name for binary downloads (darwin or linux)
# Outputs the OS name to stdout; returns 1 on unsupported OS
_koyeb_detect_os() {
case "$(uname -s)" in
Darwin) os="darwin" ;;
Linux) os="linux" ;;
Darwin) echo "darwin" ;;
Linux) echo "linux" ;;
*)
log_error "Unsupported operating system: $(uname -s)"
return 1
;;
esac
}

# Detect CPU architecture for binary downloads (amd64 or arm64)
# Outputs the arch name to stdout; returns 1 on unsupported architecture
_koyeb_detect_arch() {
case "$(uname -m)" in
x86_64|amd64) arch="amd64" ;;
arm64|aarch64) arch="arm64" ;;
x86_64|amd64) echo "amd64" ;;
arm64|aarch64) echo "arm64" ;;
*)
log_error "Unsupported architecture: $(uname -m)"
return 1
;;
esac
}

# Download and install the Koyeb CLI binary
# Usage: _koyeb_install_cli OS ARCH
_koyeb_install_cli() {
local os="$1" arch="$2"
local install_dir="$HOME/.koyeb/bin"
mkdir -p "$install_dir"

Expand All@@ -72,6 +71,22 @@ ensure_koyeb_cli() {
log_error "Koyeb CLI not found in PATH after installation"
return 1
fi
}

# Ensure Koyeb CLI is installed
ensure_koyeb_cli() {
if command -v koyeb &>/dev/null; then
log_info "Koyeb CLI available"
return 0
fi

log_step "Installing Koyeb CLI..."

local os arch
os=$(_koyeb_detect_os) || return 1
arch=$(_koyeb_detect_arch) || return 1

_koyeb_install_cli "$os" "$arch" || return 1

log_info "Koyeb CLI installed"
}
Expand Down
82 changes: 50 additions & 32 deletions webdock/lib/common.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -134,56 +134,74 @@ _wait_for_webdock_server() {
WEBDOCK_SERVER_IP "Server" "${max_attempts}"
}

# Fetch all SSH public key IDs from the Webdock account
# Returns: JSON array of key IDs (e.g., [1, 2, 3]) or "[]" if none
_webdock_get_public_key_ids() {
local response
response=$(webdock_api GET "/account/publicKeys")
echo "$response" | python3 -c "
import json, sys
data = json.loads(sys.stdin.read())
if isinstance(data, list):
ids = [k['id'] for k in data if 'id' in k]
else:
ids = []
print(json.dumps(ids))
" 2>/dev/null || echo "[]"
}

# Validate Webdock server creation inputs
# Usage: _webdock_validate_inputs LOCATION PROFILE IMAGE SLUG
_webdock_validate_inputs() {
validate_resource_name "$1" || { log_error "Invalid WEBDOCK_LOCATION"; return 1; }
validate_resource_name "$2" || { log_error "Invalid WEBDOCK_PROFILE"; return 1; }
validate_resource_name "$3" || { log_error "Invalid WEBDOCK_IMAGE"; return 1; }
validate_resource_name "$4" || { log_error "Invalid server slug"; return 1; }
}

# Extract server slug from creation response or report failure
# Sets: WEBDOCK_SERVER_SLUG on success
# Usage: _webdock_handle_create_response RESPONSE
_webdock_handle_create_response() {
local response="$1"
if echo "$response" | grep -q '"slug"'; then
WEBDOCK_SERVER_SLUG=$(_extract_json_field "$response" "d['slug']")
export WEBDOCK_SERVER_SLUG
log_info "Server created: slug=$WEBDOCK_SERVER_SLUG"
return 0
fi
log_error "Failed to create Webdock server"
log_error "API Error: $(extract_api_error_message "$response" "$response")"
log_warn "Common issues:"
log_warn " - Insufficient account balance"
log_warn " - Profile/location unavailable (try different WEBDOCK_PROFILE or WEBDOCK_LOCATION)"
log_warn " - Server limit reached"
log_warn " - Slug already in use"
log_warn "Check your dashboard: https://my.webdock.io/"
return 1
}

create_server() {
local name="$1"
local slug="${name}"
local location_id="${WEBDOCK_LOCATION:-fi}"
local profile_slug="${WEBDOCK_PROFILE:-webdockmicro}"
local image_slug="${WEBDOCK_IMAGE:-ubuntu2404}"

# Validate env var inputs to prevent injection into Python code
validate_resource_name "$location_id" || { log_error "Invalid WEBDOCK_LOCATION"; return 1; }
validate_resource_name "$profile_slug" || { log_error "Invalid WEBDOCK_PROFILE"; return 1; }
validate_resource_name "$image_slug" || { log_error "Invalid WEBDOCK_IMAGE"; return 1; }
validate_resource_name "$slug" || { log_error "Invalid server slug"; return 1; }
_webdock_validate_inputs "$location_id" "$profile_slug" "$image_slug" "$slug" || return 1

log_step "Creating Webdock server '$name' (profile: $profile_slug, location: $location_id)..."

# Get all SSH public key IDs
local public_keys_response
public_keys_response=$(webdock_api GET "/account/publicKeys")
local public_key_ids
public_key_ids=$(echo "$public_keys_response" | python3 -c "
import json, sys
data = json.loads(sys.stdin.read())
if isinstance(data, list):
ids = [k['id'] for k in data if 'id' in k]
else:
ids = []
print(json.dumps(ids))
" 2>/dev/null || echo "[]")
public_key_ids=$(_webdock_get_public_key_ids)

local body
body=$(_webdock_build_server_body "$name" "$slug" "$location_id" "$profile_slug" "$image_slug" "$public_key_ids")

local response
response=$(webdock_api POST "/servers" "$body")

if echo "$response" | grep -q '"slug"'; then
WEBDOCK_SERVER_SLUG=$(echo "$response" | python3 -c "import json,sys; print(json.loads(sys.stdin.read())['slug'])")
export WEBDOCK_SERVER_SLUG
log_info "Server created: slug=$WEBDOCK_SERVER_SLUG"
else
log_error "Failed to create Webdock server"
log_error "API Error: $(extract_api_error_message "$response" "$response")"
log_warn "Common issues:"
log_warn " - Insufficient account balance"
log_warn " - Profile/location unavailable (try different WEBDOCK_PROFILE or WEBDOCK_LOCATION)"
log_warn " - Server limit reached"
log_warn " - Slug already in use"
log_warn "Check your dashboard: https://my.webdock.io/"
return 1
fi
_webdock_handle_create_response "$response" || return 1

_wait_for_webdock_server "$WEBDOCK_SERVER_SLUG"
}
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 32 additions & 17 deletions koyeb/lib/common.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -23,37 +23,36 @@ fi
# Koyeb specific functions
# ============================================================

# Ensure Koyeb CLI is installed
ensure_koyeb_cli() {
if command -v koyeb &>/dev/null; then
log_info "Koyeb CLI available"
return 0
fi

log_step "Installing Koyeb CLI..."

# Detect OS and architecture
local os=""
local arch=""

# Detect OS name for binary downloads (darwin or linux)
# Outputs the OS name to stdout; returns 1 on unsupported OS
_koyeb_detect_os() {
case "$(uname -s)" in
Darwin) os="darwin" ;;
Linux) os="linux" ;;
Darwin) echo "darwin" ;;
Linux) echo "linux" ;;
*)
log_error "Unsupported operating system: $(uname -s)"
return 1
;;
esac
}

# Detect CPU architecture for binary downloads (amd64 or arm64)
# Outputs the arch name to stdout; returns 1 on unsupported architecture
_koyeb_detect_arch() {
case "$(uname -m)" in
x86_64|amd64) arch="amd64" ;;
arm64|aarch64) arch="arm64" ;;
x86_64|amd64) echo "amd64" ;;
arm64|aarch64) echo "arm64" ;;
*)
log_error "Unsupported architecture: $(uname -m)"
return 1
;;
esac
}

# Download and install the Koyeb CLI binary
# Usage: _koyeb_install_cli OS ARCH
_koyeb_install_cli() {
local os="$1" arch="$2"
local install_dir="$HOME/.koyeb/bin"
mkdir -p "$install_dir"

Expand All@@ -72,6 +71,22 @@ ensure_koyeb_cli() {
log_error "Koyeb CLI not found in PATH after installation"
return 1
fi
}

# Ensure Koyeb CLI is installed
ensure_koyeb_cli() {
if command -v koyeb &>/dev/null; then
log_info "Koyeb CLI available"
return 0
fi

log_step "Installing Koyeb CLI..."

local os arch
os=$(_koyeb_detect_os) || return 1
arch=$(_koyeb_detect_arch) || return 1

_koyeb_install_cli "$os" "$arch" || return 1

log_info "Koyeb CLI installed"
}
Expand Down
82 changes: 50 additions & 32 deletions webdock/lib/common.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -134,56 +134,74 @@ _wait_for_webdock_server() {
WEBDOCK_SERVER_IP "Server" "${max_attempts}"
}

# Fetch all SSH public key IDs from the Webdock account
# Returns: JSON array of key IDs (e.g., [1, 2, 3]) or "[]" if none
_webdock_get_public_key_ids() {
local response
response=$(webdock_api GET "/account/publicKeys")
echo "$response" | python3 -c "
import json, sys
data = json.loads(sys.stdin.read())
if isinstance(data, list):
ids = [k['id'] for k in data if 'id' in k]
else:
ids = []
print(json.dumps(ids))
" 2>/dev/null || echo "[]"
}

# Validate Webdock server creation inputs
# Usage: _webdock_validate_inputs LOCATION PROFILE IMAGE SLUG
_webdock_validate_inputs() {
validate_resource_name "$1" || { log_error "Invalid WEBDOCK_LOCATION"; return 1; }
validate_resource_name "$2" || { log_error "Invalid WEBDOCK_PROFILE"; return 1; }
validate_resource_name "$3" || { log_error "Invalid WEBDOCK_IMAGE"; return 1; }
validate_resource_name "$4" || { log_error "Invalid server slug"; return 1; }
}

# Extract server slug from creation response or report failure
# Sets: WEBDOCK_SERVER_SLUG on success
# Usage: _webdock_handle_create_response RESPONSE
_webdock_handle_create_response() {
local response="$1"
if echo "$response" | grep -q '"slug"'; then
WEBDOCK_SERVER_SLUG=$(_extract_json_field "$response" "d['slug']")
export WEBDOCK_SERVER_SLUG
log_info "Server created: slug=$WEBDOCK_SERVER_SLUG"
return 0
fi
log_error "Failed to create Webdock server"
log_error "API Error: $(extract_api_error_message "$response" "$response")"
log_warn "Common issues:"
log_warn " - Insufficient account balance"
log_warn " - Profile/location unavailable (try different WEBDOCK_PROFILE or WEBDOCK_LOCATION)"
log_warn " - Server limit reached"
log_warn " - Slug already in use"
log_warn "Check your dashboard: https://my.webdock.io/"
return 1
}

create_server() {
local name="$1"
local slug="${name}"
local location_id="${WEBDOCK_LOCATION:-fi}"
local profile_slug="${WEBDOCK_PROFILE:-webdockmicro}"
local image_slug="${WEBDOCK_IMAGE:-ubuntu2404}"

# Validate env var inputs to prevent injection into Python code
validate_resource_name "$location_id" || { log_error "Invalid WEBDOCK_LOCATION"; return 1; }
validate_resource_name "$profile_slug" || { log_error "Invalid WEBDOCK_PROFILE"; return 1; }
validate_resource_name "$image_slug" || { log_error "Invalid WEBDOCK_IMAGE"; return 1; }
validate_resource_name "$slug" || { log_error "Invalid server slug"; return 1; }
_webdock_validate_inputs "$location_id" "$profile_slug" "$image_slug" "$slug" || return 1

log_step "Creating Webdock server '$name' (profile: $profile_slug, location: $location_id)..."

# Get all SSH public key IDs
local public_keys_response
public_keys_response=$(webdock_api GET "/account/publicKeys")
local public_key_ids
public_key_ids=$(echo "$public_keys_response" | python3 -c "
import json, sys
data = json.loads(sys.stdin.read())
if isinstance(data, list):
ids = [k['id'] for k in data if 'id' in k]
else:
ids = []
print(json.dumps(ids))
" 2>/dev/null || echo "[]")
public_key_ids=$(_webdock_get_public_key_ids)

local body
body=$(_webdock_build_server_body "$name" "$slug" "$location_id" "$profile_slug" "$image_slug" "$public_key_ids")

local response
response=$(webdock_api POST "/servers" "$body")

if echo "$response" | grep -q '"slug"'; then
WEBDOCK_SERVER_SLUG=$(echo "$response" | python3 -c "import json,sys; print(json.loads(sys.stdin.read())['slug'])")
export WEBDOCK_SERVER_SLUG
log_info "Server created: slug=$WEBDOCK_SERVER_SLUG"
else
log_error "Failed to create Webdock server"
log_error "API Error: $(extract_api_error_message "$response" "$response")"
log_warn "Common issues:"
log_warn " - Insufficient account balance"
log_warn " - Profile/location unavailable (try different WEBDOCK_PROFILE or WEBDOCK_LOCATION)"
log_warn " - Server limit reached"
log_warn " - Slug already in use"
log_warn "Check your dashboard: https://my.webdock.io/"
return 1
fi
_webdock_handle_create_response "$response" || return 1

_wait_for_webdock_server "$WEBDOCK_SERVER_SLUG"
}
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 32 additions & 17 deletions koyeb/lib/common.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -23,37 +23,36 @@ fi
# Koyeb specific functions
# ============================================================

# Ensure Koyeb CLI is installed
ensure_koyeb_cli() {
if command -v koyeb &>/dev/null; then
log_info "Koyeb CLI available"
return 0
fi

log_step "Installing Koyeb CLI..."

# Detect OS and architecture
local os=""
local arch=""

# Detect OS name for binary downloads (darwin or linux)
# Outputs the OS name to stdout; returns 1 on unsupported OS
_koyeb_detect_os() {
case "$(uname -s)" in
Darwin) os="darwin" ;;
Linux) os="linux" ;;
Darwin) echo "darwin" ;;
Linux) echo "linux" ;;
*)
log_error "Unsupported operating system: $(uname -s)"
return 1
;;
esac
}

# Detect CPU architecture for binary downloads (amd64 or arm64)
# Outputs the arch name to stdout; returns 1 on unsupported architecture
_koyeb_detect_arch() {
case "$(uname -m)" in
x86_64|amd64) arch="amd64" ;;
arm64|aarch64) arch="arm64" ;;
x86_64|amd64) echo "amd64" ;;
arm64|aarch64) echo "arm64" ;;
*)
log_error "Unsupported architecture: $(uname -m)"
return 1
;;
esac
}

# Download and install the Koyeb CLI binary
# Usage: _koyeb_install_cli OS ARCH
_koyeb_install_cli() {
local os="$1" arch="$2"
local install_dir="$HOME/.koyeb/bin"
mkdir -p "$install_dir"

Expand All@@ -72,6 +71,22 @@ ensure_koyeb_cli() {
log_error "Koyeb CLI not found in PATH after installation"
return 1
fi
}

# Ensure Koyeb CLI is installed
ensure_koyeb_cli() {
if command -v koyeb &>/dev/null; then
log_info "Koyeb CLI available"
return 0
fi

log_step "Installing Koyeb CLI..."

local os arch
os=$(_koyeb_detect_os) || return 1
arch=$(_koyeb_detect_arch) || return 1

_koyeb_install_cli "$os" "$arch" || return 1

log_info "Koyeb CLI installed"
}
Expand Down
82 changes: 50 additions & 32 deletions webdock/lib/common.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -134,56 +134,74 @@ _wait_for_webdock_server() {
WEBDOCK_SERVER_IP "Server" "${max_attempts}"
}

# Fetch all SSH public key IDs from the Webdock account
# Returns: JSON array of key IDs (e.g., [1, 2, 3]) or "[]" if none
_webdock_get_public_key_ids() {
local response
response=$(webdock_api GET "/account/publicKeys")
echo "$response" | python3 -c "
import json, sys
data = json.loads(sys.stdin.read())
if isinstance(data, list):
ids = [k['id'] for k in data if 'id' in k]
else:
ids = []
print(json.dumps(ids))
" 2>/dev/null || echo "[]"
}

# Validate Webdock server creation inputs
# Usage: _webdock_validate_inputs LOCATION PROFILE IMAGE SLUG
_webdock_validate_inputs() {
validate_resource_name "$1" || { log_error "Invalid WEBDOCK_LOCATION"; return 1; }
validate_resource_name "$2" || { log_error "Invalid WEBDOCK_PROFILE"; return 1; }
validate_resource_name "$3" || { log_error "Invalid WEBDOCK_IMAGE"; return 1; }
validate_resource_name "$4" || { log_error "Invalid server slug"; return 1; }
}

# Extract server slug from creation response or report failure
# Sets: WEBDOCK_SERVER_SLUG on success
# Usage: _webdock_handle_create_response RESPONSE
_webdock_handle_create_response() {
local response="$1"
if echo "$response" | grep -q '"slug"'; then
WEBDOCK_SERVER_SLUG=$(_extract_json_field "$response" "d['slug']")
export WEBDOCK_SERVER_SLUG
log_info "Server created: slug=$WEBDOCK_SERVER_SLUG"
return 0
fi
log_error "Failed to create Webdock server"
log_error "API Error: $(extract_api_error_message "$response" "$response")"
log_warn "Common issues:"
log_warn " - Insufficient account balance"
log_warn " - Profile/location unavailable (try different WEBDOCK_PROFILE or WEBDOCK_LOCATION)"
log_warn " - Server limit reached"
log_warn " - Slug already in use"
log_warn "Check your dashboard: https://my.webdock.io/"
return 1
}

create_server() {
local name="$1"
local slug="${name}"
local location_id="${WEBDOCK_LOCATION:-fi}"
local profile_slug="${WEBDOCK_PROFILE:-webdockmicro}"
local image_slug="${WEBDOCK_IMAGE:-ubuntu2404}"

# Validate env var inputs to prevent injection into Python code
validate_resource_name "$location_id" || { log_error "Invalid WEBDOCK_LOCATION"; return 1; }
validate_resource_name "$profile_slug" || { log_error "Invalid WEBDOCK_PROFILE"; return 1; }
validate_resource_name "$image_slug" || { log_error "Invalid WEBDOCK_IMAGE"; return 1; }
validate_resource_name "$slug" || { log_error "Invalid server slug"; return 1; }
_webdock_validate_inputs "$location_id" "$profile_slug" "$image_slug" "$slug" || return 1

log_step "Creating Webdock server '$name' (profile: $profile_slug, location: $location_id)..."

# Get all SSH public key IDs
local public_keys_response
public_keys_response=$(webdock_api GET "/account/publicKeys")
local public_key_ids
public_key_ids=$(echo "$public_keys_response" | python3 -c "
import json, sys
data = json.loads(sys.stdin.read())
if isinstance(data, list):
ids = [k['id'] for k in data if 'id' in k]
else:
ids = []
print(json.dumps(ids))
" 2>/dev/null || echo "[]")
public_key_ids=$(_webdock_get_public_key_ids)

local body
body=$(_webdock_build_server_body "$name" "$slug" "$location_id" "$profile_slug" "$image_slug" "$public_key_ids")

local response
response=$(webdock_api POST "/servers" "$body")

if echo "$response" | grep -q '"slug"'; then
WEBDOCK_SERVER_SLUG=$(echo "$response" | python3 -c "import json,sys; print(json.loads(sys.stdin.read())['slug'])")
export WEBDOCK_SERVER_SLUG
log_info "Server created: slug=$WEBDOCK_SERVER_SLUG"
else
log_error "Failed to create Webdock server"
log_error "API Error: $(extract_api_error_message "$response" "$response")"
log_warn "Common issues:"
log_warn " - Insufficient account balance"
log_warn " - Profile/location unavailable (try different WEBDOCK_PROFILE or WEBDOCK_LOCATION)"
log_warn " - Server limit reached"
log_warn " - Slug already in use"
log_warn "Check your dashboard: https://my.webdock.io/"
return 1
fi
_webdock_handle_create_response "$response" || return 1

_wait_for_webdock_server "$WEBDOCK_SERVER_SLUG"
}
Expand Down