Initial commit
This commit is contained in:
56
skills/weeknotes-blog-post-composer/scripts/calculate-week.py
Executable file
56
skills/weeknotes-blog-post-composer/scripts/calculate-week.py
Executable file
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Calculate the current ISO week number and generate the weeknotes filename.
|
||||
|
||||
Usage:
|
||||
./scripts/calculate-week.py [--date YYYY-MM-DD]
|
||||
|
||||
If no date is provided, uses today's date.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import os
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
def calculate_week_info(date=None):
|
||||
"""Calculate week information for the given date (or today)."""
|
||||
if date is None:
|
||||
date = datetime.now()
|
||||
elif isinstance(date, str):
|
||||
date = datetime.strptime(date, '%Y-%m-%d')
|
||||
|
||||
week_number = date.isocalendar()[1]
|
||||
year = date.year
|
||||
date_str = date.strftime('%Y-%m-%d')
|
||||
|
||||
return {
|
||||
'date': date_str,
|
||||
'year': year,
|
||||
'week': week_number,
|
||||
'filename': f"content/posts/{year}/{date_str}-w{week_number:02d}.md",
|
||||
'title': f"Weeknotes: {year} Week {week_number}"
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='Calculate weeknotes week number and filename')
|
||||
parser.add_argument('--date', type=str, help='Date in YYYY-MM-DD format (default: today)')
|
||||
parser.add_argument('--json', action='store_true', help='Output as JSON')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
info = calculate_week_info(args.date)
|
||||
|
||||
if args.json:
|
||||
import json
|
||||
print(json.dumps(info, indent=2))
|
||||
else:
|
||||
print(f"Date: {info['date']}")
|
||||
print(f"ISO Week: {info['week']}")
|
||||
print(f"Title: {info['title']}")
|
||||
print(f"Filename: {info['filename']}")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
89
skills/weeknotes-blog-post-composer/scripts/download-binaries.sh
Executable file
89
skills/weeknotes-blog-post-composer/scripts/download-binaries.sh
Executable file
@@ -0,0 +1,89 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
SKILL_DIR="$(dirname "$SCRIPT_DIR")"
|
||||
BIN_DIR="${SKILL_DIR}/bin"
|
||||
|
||||
echo "╔════════════════════════════════════════╗"
|
||||
echo "║ Weeknotes Binary Downloader ║"
|
||||
echo "╚════════════════════════════════════════╝"
|
||||
echo ""
|
||||
|
||||
# Create bin directory structure
|
||||
mkdir -p "${BIN_DIR}/darwin-arm64"
|
||||
mkdir -p "${BIN_DIR}/darwin-amd64"
|
||||
mkdir -p "${BIN_DIR}/linux-amd64"
|
||||
|
||||
# Function to download and extract a GitHub release
|
||||
download_tool() {
|
||||
local repo=$1
|
||||
local tool_name=$2
|
||||
local platform=$3
|
||||
local arch=$4
|
||||
|
||||
echo "📦 Downloading ${tool_name} for ${platform}-${arch}..."
|
||||
|
||||
# Construct the asset name based on the naming convention
|
||||
local archive_name="${tool_name}-${platform}-${arch}.tar.gz"
|
||||
local asset_url="https://github.com/${repo}/releases/download/latest/${archive_name}"
|
||||
local temp_archive="/tmp/${archive_name}"
|
||||
local target_dir="${BIN_DIR}/${platform}-${arch}"
|
||||
local target_binary="${target_dir}/${tool_name}"
|
||||
|
||||
# Download the archive
|
||||
echo " Downloading from ${asset_url}..."
|
||||
if curl -L -f -o "${temp_archive}" "${asset_url}"; then
|
||||
echo " ✅ Downloaded archive"
|
||||
|
||||
# Extract the binary from the archive
|
||||
echo " Extracting binary..."
|
||||
tar -xzf "${temp_archive}" -C "${target_dir}" "${tool_name}" 2>/dev/null || {
|
||||
# If extraction with specific file fails, extract all and find the binary
|
||||
tar -xzf "${temp_archive}" -C /tmp/
|
||||
find /tmp -name "${tool_name}" -type f -exec mv {} "${target_binary}" \;
|
||||
}
|
||||
|
||||
# Make binary executable
|
||||
chmod +x "${target_binary}"
|
||||
|
||||
# Cleanup
|
||||
rm -f "${temp_archive}"
|
||||
|
||||
# Verify the binary exists
|
||||
if [ -f "${target_binary}" ]; then
|
||||
echo " ✅ Installed to ${target_binary}"
|
||||
else
|
||||
echo " ❌ Failed to extract binary"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
echo " ❌ Failed to download from ${asset_url}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
}
|
||||
|
||||
# Download mastodon-to-markdown
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo "Mastodon to Markdown"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
download_tool "lmorchard/mastodon-to-markdown" "mastodon-to-markdown" "darwin" "arm64"
|
||||
download_tool "lmorchard/mastodon-to-markdown" "mastodon-to-markdown" "darwin" "amd64"
|
||||
download_tool "lmorchard/mastodon-to-markdown" "mastodon-to-markdown" "linux" "amd64"
|
||||
|
||||
# Download linkding-to-markdown
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo "Linkding to Markdown"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
download_tool "lmorchard/linkding-to-markdown" "linkding-to-markdown" "darwin" "arm64"
|
||||
download_tool "lmorchard/linkding-to-markdown" "linkding-to-markdown" "darwin" "amd64"
|
||||
download_tool "lmorchard/linkding-to-markdown" "linkding-to-markdown" "linux" "amd64"
|
||||
|
||||
echo "╔════════════════════════════════════════╗"
|
||||
echo "║ Download Complete! ║"
|
||||
echo "╚════════════════════════════════════════╝"
|
||||
echo ""
|
||||
echo "Binary locations:"
|
||||
tree "${BIN_DIR}" || ls -R "${BIN_DIR}"
|
||||
178
skills/weeknotes-blog-post-composer/scripts/fetch-sources.sh
Executable file
178
skills/weeknotes-blog-post-composer/scripts/fetch-sources.sh
Executable file
@@ -0,0 +1,178 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
SKILL_DIR="$(dirname "$SCRIPT_DIR")"
|
||||
CONFIG_FILE="${SKILL_DIR}/config/config.json"
|
||||
DATA_DIR="${SKILL_DIR}/data"
|
||||
|
||||
# Default to last 7 days (from 7 days ago through today)
|
||||
# Note: The APIs treat end date as exclusive, so we use tomorrow's date
|
||||
get_week_dates() {
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
# macOS date command
|
||||
START_DATE=$(date -v-7d +%Y-%m-%d)
|
||||
END_DATE=$(date -v+1d +%Y-%m-%d)
|
||||
else
|
||||
# Linux date command
|
||||
START_DATE=$(date -d "7 days ago" +%Y-%m-%d)
|
||||
END_DATE=$(date -d "tomorrow" +%Y-%m-%d)
|
||||
fi
|
||||
}
|
||||
|
||||
# Parse command line arguments
|
||||
START_DATE=""
|
||||
END_DATE=""
|
||||
OUTPUT_DIR="${DATA_DIR}/latest"
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--start)
|
||||
START_DATE="$2"
|
||||
shift 2
|
||||
;;
|
||||
--end)
|
||||
END_DATE="$2"
|
||||
shift 2
|
||||
;;
|
||||
--output-dir)
|
||||
OUTPUT_DIR="$2"
|
||||
shift 2
|
||||
;;
|
||||
-h|--help)
|
||||
echo "Usage: fetch-sources.sh [options]"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " --start DATE Start date (YYYY-MM-DD), defaults to Monday of current week"
|
||||
echo " --end DATE End date (YYYY-MM-DD), defaults to Sunday of current week"
|
||||
echo " --output-dir DIR Output directory (default: data/latest)"
|
||||
echo " -h, --help Show this help message"
|
||||
echo ""
|
||||
echo "Examples:"
|
||||
echo " fetch-sources.sh # Fetch this week"
|
||||
echo " fetch-sources.sh --start 2025-11-01 --end 2025-11-07"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $1"
|
||||
echo "Use --help for usage information"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# If dates not provided, use current week
|
||||
if [ -z "$START_DATE" ] || [ -z "$END_DATE" ]; then
|
||||
get_week_dates
|
||||
fi
|
||||
|
||||
echo "╔════════════════════════════════════════╗"
|
||||
echo "║ Weeknotes Source Fetcher ║"
|
||||
echo "╚════════════════════════════════════════╝"
|
||||
echo ""
|
||||
echo "Fetching data from ${START_DATE} to ${END_DATE}"
|
||||
echo ""
|
||||
|
||||
# Check if configured
|
||||
if [ ! -f "${CONFIG_FILE}" ]; then
|
||||
echo "❌ Not configured yet. Running setup..."
|
||||
echo ""
|
||||
"${SCRIPT_DIR}/setup.sh"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Detect platform
|
||||
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
|
||||
ARCH=$(uname -m)
|
||||
|
||||
case $ARCH in
|
||||
x86_64) ARCH="amd64" ;;
|
||||
aarch64|arm64) ARCH="arm64" ;;
|
||||
esac
|
||||
|
||||
BIN_DIR="${SKILL_DIR}/bin/${OS}-${ARCH}"
|
||||
|
||||
# Check if binaries exist
|
||||
if [ ! -f "${BIN_DIR}/mastodon-to-markdown" ] || [ ! -f "${BIN_DIR}/linkding-to-markdown" ]; then
|
||||
echo "❌ Binaries not found for platform: ${OS}-${ARCH}"
|
||||
echo " Please run scripts/download-binaries.sh first"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Load config using jq (if not available, use basic parsing)
|
||||
if command -v jq &> /dev/null; then
|
||||
MASTODON_SERVER=$(jq -r .mastodon.server "${CONFIG_FILE}")
|
||||
MASTODON_TOKEN=$(jq -r .mastodon.token "${CONFIG_FILE}")
|
||||
LINKDING_URL=$(jq -r .linkding.url "${CONFIG_FILE}")
|
||||
LINKDING_TOKEN=$(jq -r .linkding.token "${CONFIG_FILE}")
|
||||
else
|
||||
echo "⚠️ Warning: jq not found. Using basic config parsing."
|
||||
echo " Install jq for better config handling: brew install jq"
|
||||
# Basic parsing fallback (not recommended for production)
|
||||
MASTODON_SERVER=$(grep -o '"server"[[:space:]]*:[[:space:]]*"[^"]*"' "${CONFIG_FILE}" | cut -d'"' -f4 | head -1)
|
||||
MASTODON_TOKEN=$(grep -o '"token"[[:space:]]*:[[:space:]]*"[^"]*"' "${CONFIG_FILE}" | cut -d'"' -f4 | head -1)
|
||||
LINKDING_URL=$(grep -o '"url"[[:space:]]*:[[:space:]]*"[^"]*"' "${CONFIG_FILE}" | cut -d'"' -f4 | tail -1)
|
||||
LINKDING_TOKEN=$(grep -o '"token"[[:space:]]*:[[:space:]]*"[^"]*"' "${CONFIG_FILE}" | cut -d'"' -f4 | tail -1)
|
||||
fi
|
||||
|
||||
# Create output directory
|
||||
mkdir -p "${OUTPUT_DIR}"
|
||||
|
||||
# Create config files for the tools
|
||||
MASTODON_CONFIG="${OUTPUT_DIR}/mastodon-config.yaml"
|
||||
LINKDING_CONFIG="${OUTPUT_DIR}/linkding-config.yaml"
|
||||
|
||||
cat > "${MASTODON_CONFIG}" <<EOF
|
||||
mastodon:
|
||||
server: "${MASTODON_SERVER}"
|
||||
access_token: "${MASTODON_TOKEN}"
|
||||
EOF
|
||||
|
||||
cat > "${LINKDING_CONFIG}" <<EOF
|
||||
linkding:
|
||||
url: "${LINKDING_URL}"
|
||||
token: "${LINKDING_TOKEN}"
|
||||
EOF
|
||||
|
||||
# Fetch from Mastodon
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo "📱 Fetching Mastodon posts..."
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
|
||||
"${BIN_DIR}/mastodon-to-markdown" fetch \
|
||||
--config "${MASTODON_CONFIG}" \
|
||||
--start "${START_DATE}" \
|
||||
--end "${END_DATE}" \
|
||||
--output "${OUTPUT_DIR}/mastodon.md" \
|
||||
--verbose
|
||||
|
||||
echo "✅ Mastodon posts saved to: ${OUTPUT_DIR}/mastodon.md"
|
||||
echo ""
|
||||
|
||||
# Fetch from Linkding
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo "🔖 Fetching Linkding bookmarks..."
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
|
||||
"${BIN_DIR}/linkding-to-markdown" fetch \
|
||||
--config "${LINKDING_CONFIG}" \
|
||||
--since "${START_DATE}" \
|
||||
--until "${END_DATE}" \
|
||||
--output "${OUTPUT_DIR}/linkding.md" \
|
||||
--verbose
|
||||
|
||||
echo "✅ Linkding bookmarks saved to: ${OUTPUT_DIR}/linkding.md"
|
||||
echo ""
|
||||
|
||||
# Cleanup config files (they contain secrets)
|
||||
rm -f "${MASTODON_CONFIG}" "${LINKDING_CONFIG}"
|
||||
|
||||
echo "╔════════════════════════════════════════╗"
|
||||
echo "║ Fetch Complete! ║"
|
||||
echo "╚════════════════════════════════════════╝"
|
||||
echo ""
|
||||
echo "Output directory: ${OUTPUT_DIR}"
|
||||
echo "Files:"
|
||||
echo " - mastodon.md"
|
||||
echo " - linkding.md"
|
||||
echo ""
|
||||
102
skills/weeknotes-blog-post-composer/scripts/prepare-sources.py
Executable file
102
skills/weeknotes-blog-post-composer/scripts/prepare-sources.py
Executable file
@@ -0,0 +1,102 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Prepare fetched source data for composition.
|
||||
|
||||
This script reads the fetched markdown files and displays them for Claude
|
||||
to read and compose into a cohesive weeknotes blog post.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
from datetime import datetime, timedelta
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def get_current_week_dates():
|
||||
"""Calculate dates for the last 7 days (7 days ago to today)."""
|
||||
today = datetime.now()
|
||||
seven_days_ago = today - timedelta(days=7)
|
||||
return seven_days_ago.strftime("%Y-%m-%d"), today.strftime("%Y-%m-%d")
|
||||
|
||||
|
||||
def main():
|
||||
"""Main entry point."""
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Prepare fetched source data for weeknotes composition"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--input-dir",
|
||||
type=Path,
|
||||
help="Input directory with fetched data (default: data/latest)",
|
||||
)
|
||||
parser.add_argument("--start", help="Start date (YYYY-MM-DD)")
|
||||
parser.add_argument("--end", help="End date (YYYY-MM-DD)")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Set default input directory
|
||||
if not args.input_dir:
|
||||
args.input_dir = Path(__file__).parent.parent / "data" / "latest"
|
||||
|
||||
print("╔════════════════════════════════════════╗")
|
||||
print("║ Weeknotes Source Preparation ║")
|
||||
print("╚════════════════════════════════════════╝")
|
||||
print()
|
||||
|
||||
# Check if input directory exists
|
||||
if not args.input_dir.exists():
|
||||
print(f"❌ Input directory not found: {args.input_dir}")
|
||||
print(" Please run fetch-sources.sh first")
|
||||
sys.exit(1)
|
||||
|
||||
# Determine dates
|
||||
if not args.start or not args.end:
|
||||
args.start, args.end = get_current_week_dates()
|
||||
|
||||
week_range = f"{args.start} to {args.end}"
|
||||
print(f"📅 Date range: {week_range}")
|
||||
print()
|
||||
|
||||
# Check for source files
|
||||
mastodon_file = args.input_dir / "mastodon.md"
|
||||
linkding_file = args.input_dir / "linkding.md"
|
||||
|
||||
has_mastodon = mastodon_file.exists()
|
||||
has_linkding = linkding_file.exists()
|
||||
|
||||
if not has_mastodon and not has_linkding:
|
||||
print("❌ No source data found!")
|
||||
print(f" Expected files in: {args.input_dir}")
|
||||
sys.exit(1)
|
||||
|
||||
print("📂 Available source data:")
|
||||
if has_mastodon:
|
||||
size = mastodon_file.stat().st_size
|
||||
print(f" ✅ Mastodon posts: {mastodon_file} ({size:,} bytes)")
|
||||
else:
|
||||
print(f" ⚠️ No Mastodon data: {mastodon_file}")
|
||||
|
||||
if has_linkding:
|
||||
size = linkding_file.stat().st_size
|
||||
print(f" ✅ Linkding bookmarks: {linkding_file} ({size:,} bytes)")
|
||||
else:
|
||||
print(f" ⚠️ No Linkding data: {linkding_file}")
|
||||
|
||||
print()
|
||||
print("╔════════════════════════════════════════╗")
|
||||
print("║ Ready for Composition ║")
|
||||
print("╚════════════════════════════════════════╝")
|
||||
print()
|
||||
print("Source files are ready to be read and composed into a weeknotes post.")
|
||||
print()
|
||||
print("Next steps:")
|
||||
print(f"1. Read: {mastodon_file}")
|
||||
if has_linkding:
|
||||
print(f"2. Read: {linkding_file}")
|
||||
print(f"3. Compose conversational weeknotes for {week_range}")
|
||||
print("4. Write the composed post with Jekyll frontmatter")
|
||||
print()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
226
skills/weeknotes-blog-post-composer/scripts/setup.sh
Executable file
226
skills/weeknotes-blog-post-composer/scripts/setup.sh
Executable file
@@ -0,0 +1,226 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
SKILL_DIR="$(dirname "$SCRIPT_DIR")"
|
||||
CONFIG_FILE="${SKILL_DIR}/config/config.json"
|
||||
DATA_DIR="${SKILL_DIR}/data"
|
||||
|
||||
echo "╔════════════════════════════════════════╗"
|
||||
echo "║ Weeknotes Composer Setup ║"
|
||||
echo "╚════════════════════════════════════════╝"
|
||||
echo ""
|
||||
|
||||
# Check if config already exists
|
||||
if [ -f "${CONFIG_FILE}" ]; then
|
||||
echo "⚠️ Configuration already exists."
|
||||
read -p "Do you want to reconfigure? (y/N): " RECONFIGURE
|
||||
if [[ ! "$RECONFIGURE" =~ ^[Yy]$ ]]; then
|
||||
echo "Setup cancelled."
|
||||
exit 0
|
||||
fi
|
||||
echo ""
|
||||
fi
|
||||
|
||||
echo "This setup will configure connections to your data sources."
|
||||
echo ""
|
||||
|
||||
# ============================================================================
|
||||
# Mastodon Configuration
|
||||
# ============================================================================
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo "📱 Mastodon Configuration"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo ""
|
||||
echo "Enter your Mastodon instance details."
|
||||
echo "Example server: https://mastodon.social"
|
||||
echo ""
|
||||
|
||||
read -p "Mastodon server URL: " MASTODON_SERVER
|
||||
MASTODON_SERVER="${MASTODON_SERVER%/}"
|
||||
|
||||
# Validate URL format
|
||||
if [[ ! "$MASTODON_SERVER" =~ ^https?:// ]]; then
|
||||
echo "❌ Error: URL must start with http:// or https://"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "To get your Mastodon access token:"
|
||||
echo "1. Log into your Mastodon instance"
|
||||
echo "2. Go to Settings → Development → New Application"
|
||||
echo "3. Give it a name (e.g., 'Weeknotes Composer')"
|
||||
echo "4. Grant 'read' permissions"
|
||||
echo "5. Copy the access token"
|
||||
echo ""
|
||||
|
||||
read -sp "Mastodon access token: " MASTODON_TOKEN
|
||||
echo ""
|
||||
|
||||
# Validate token is not empty
|
||||
if [ -z "$MASTODON_TOKEN" ]; then
|
||||
echo "❌ Error: Access token cannot be empty"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test the Mastodon connection
|
||||
echo ""
|
||||
echo "🔍 Testing Mastodon connection..."
|
||||
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
|
||||
"${MASTODON_SERVER}/api/v1/accounts/verify_credentials" \
|
||||
-H "Authorization: Bearer ${MASTODON_TOKEN}")
|
||||
|
||||
if [ "$HTTP_CODE" -eq 200 ]; then
|
||||
echo "✅ Mastodon connection successful!"
|
||||
else
|
||||
echo "❌ Mastodon connection failed (HTTP ${HTTP_CODE})"
|
||||
echo " Please check your server URL and token."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# ============================================================================
|
||||
# Linkding Configuration
|
||||
# ============================================================================
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo "🔖 Linkding Configuration"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo ""
|
||||
echo "Enter your Linkding instance details."
|
||||
echo "Example: https://linkding.example.com"
|
||||
echo ""
|
||||
|
||||
read -p "Linkding URL: " LINKDING_URL
|
||||
LINKDING_URL="${LINKDING_URL%/}"
|
||||
|
||||
# Validate URL format
|
||||
if [[ ! "$LINKDING_URL" =~ ^https?:// ]]; then
|
||||
echo "❌ Error: URL must start with http:// or https://"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "To get your Linkding API token:"
|
||||
echo "1. Log into your Linkding instance"
|
||||
echo "2. Go to Settings → Integrations"
|
||||
echo "3. Click 'Create Token'"
|
||||
echo "4. Copy the generated token"
|
||||
echo ""
|
||||
|
||||
read -sp "Linkding API token: " LINKDING_TOKEN
|
||||
echo ""
|
||||
|
||||
# Validate token is not empty
|
||||
if [ -z "$LINKDING_TOKEN" ]; then
|
||||
echo "❌ Error: API token cannot be empty"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test the Linkding connection
|
||||
echo ""
|
||||
echo "🔍 Testing Linkding connection..."
|
||||
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
|
||||
"${LINKDING_URL}/api/bookmarks/?limit=1" \
|
||||
-H "Authorization: Token ${LINKDING_TOKEN}")
|
||||
|
||||
if [ "$HTTP_CODE" -eq 200 ]; then
|
||||
echo "✅ Linkding connection successful!"
|
||||
else
|
||||
echo "❌ Linkding connection failed (HTTP ${HTTP_CODE})"
|
||||
echo " Please check your URL and token."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# ============================================================================
|
||||
# Style Reference Configuration (Optional)
|
||||
# ============================================================================
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo "🎨 Style Reference (Optional)"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo ""
|
||||
echo "Enter a URL to your past weeknotes archive for style reference."
|
||||
echo "This helps maintain consistent voice and tone in composed posts."
|
||||
echo "Example: https://blog.example.com/tag/weeknotes/"
|
||||
echo ""
|
||||
echo "Leave blank to skip style reference."
|
||||
echo ""
|
||||
|
||||
read -p "Weeknotes archive URL (optional): " WEEKNOTES_ARCHIVE_URL
|
||||
|
||||
# Remove trailing slash if present
|
||||
WEEKNOTES_ARCHIVE_URL="${WEEKNOTES_ARCHIVE_URL%/}"
|
||||
|
||||
# Validate URL format if provided
|
||||
if [ -n "$WEEKNOTES_ARCHIVE_URL" ] && [[ ! "$WEEKNOTES_ARCHIVE_URL" =~ ^https?:// ]]; then
|
||||
echo "⚠️ Warning: URL should start with http:// or https://"
|
||||
echo " Proceeding anyway..."
|
||||
fi
|
||||
|
||||
if [ -n "$WEEKNOTES_ARCHIVE_URL" ]; then
|
||||
echo "✅ Style reference URL configured"
|
||||
else
|
||||
echo "⏭️ Skipping style reference"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# ============================================================================
|
||||
# Save Configuration
|
||||
# ============================================================================
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo "💾 Saving Configuration"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo ""
|
||||
|
||||
# Create config directory if it doesn't exist
|
||||
mkdir -p "$(dirname "${CONFIG_FILE}")"
|
||||
|
||||
# Create data directory if it doesn't exist
|
||||
mkdir -p "${DATA_DIR}"
|
||||
|
||||
# Write config file with conditional weeknotes_archive
|
||||
if [ -n "$WEEKNOTES_ARCHIVE_URL" ]; then
|
||||
cat > "${CONFIG_FILE}" <<EOF
|
||||
{
|
||||
"mastodon": {
|
||||
"server": "${MASTODON_SERVER}",
|
||||
"token": "${MASTODON_TOKEN}"
|
||||
},
|
||||
"linkding": {
|
||||
"url": "${LINKDING_URL}",
|
||||
"token": "${LINKDING_TOKEN}"
|
||||
},
|
||||
"weeknotes_archive": "${WEEKNOTES_ARCHIVE_URL}",
|
||||
"created_at": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
|
||||
}
|
||||
EOF
|
||||
else
|
||||
cat > "${CONFIG_FILE}" <<EOF
|
||||
{
|
||||
"mastodon": {
|
||||
"server": "${MASTODON_SERVER}",
|
||||
"token": "${MASTODON_TOKEN}"
|
||||
},
|
||||
"linkding": {
|
||||
"url": "${LINKDING_URL}",
|
||||
"token": "${LINKDING_TOKEN}"
|
||||
},
|
||||
"created_at": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
|
||||
# Secure the config file
|
||||
chmod 600 "${CONFIG_FILE}"
|
||||
|
||||
echo "✅ Configuration saved to: ${CONFIG_FILE}"
|
||||
echo ""
|
||||
echo "╔════════════════════════════════════════╗"
|
||||
echo "║ Setup Complete! ║"
|
||||
echo "╚════════════════════════════════════════╝"
|
||||
echo ""
|
||||
echo "You can now use the weeknotes composer."
|
||||
echo ""
|
||||
Reference in New Issue
Block a user