From bb01fdecba19b9ca1dd5ec030785786682d2bd92 Mon Sep 17 00:00:00 2001 From: MhankBarBar Date: Tue, 10 Mar 2026 14:43:49 +0700 Subject: [PATCH] chore: add install scripts, update docs & add CI workflows --- .github/workflows/release-pr.yml | 30 + .github/workflows/sync-dev.yml | 31 + README.md | 27 +- docs/.vitepress/config.mts | 9 +- docs/.vitepress/theme/custom.css | 865 +++++++++++++++++++++++---- docs/getting-started/installation.md | 25 +- docs/index.md | 99 +-- install.ps1 | 152 +++++ install.sh | 148 +++++ pyproject.toml | 2 +- uv.lock | 8 +- 11 files changed, 1207 insertions(+), 189 deletions(-) create mode 100644 .github/workflows/release-pr.yml create mode 100644 .github/workflows/sync-dev.yml create mode 100644 install.ps1 create mode 100644 install.sh diff --git a/.github/workflows/release-pr.yml b/.github/workflows/release-pr.yml new file mode 100644 index 0000000..4aeb5b4 --- /dev/null +++ b/.github/workflows/release-pr.yml @@ -0,0 +1,30 @@ +name: Create Release PR + +on: + workflow_dispatch: + +permissions: + contents: read + pull-requests: write + +jobs: + create-pr: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Create or update PR + uses: repo-sync/pull-request@v2 + with: + source_branch: dev + destination_branch: master + pr_title: "chore: merge dev → master" + pr_body: | + Automated PR to merge `dev` into `master`. + + --- + _Created via Release PR workflow._ + pr_label: "release" + github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/sync-dev.yml b/.github/workflows/sync-dev.yml new file mode 100644 index 0000000..ee99cf5 --- /dev/null +++ b/.github/workflows/sync-dev.yml @@ -0,0 +1,31 @@ +name: Sync Dev from Master + +on: + pull_request: + branches: [master] + types: [closed] + workflow_dispatch: + +permissions: + contents: write + +jobs: + sync: + if: > + github.event_name == 'workflow_dispatch' || + (github.event.pull_request.merged == true && + contains(github.event.pull_request.labels.*.name, 'release')) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Sync dev from master + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git checkout dev + git merge master --no-edit + git push origin dev diff --git a/README.md b/README.md index d80d516..42d4607 100644 --- a/README.md +++ b/README.md @@ -29,28 +29,29 @@ Because life is too short for boring bots. ## Get Started -### 1. Install via pip & git +### One-Line Install +**Linux / macOS:** ```bash -pip install uv -git clone https://github.com/MhankBarBar/zero-ichi -cd zero-ichi -uv sync +curl -fsSL https://raw.githubusercontent.com/MhankBarBar/zero-ichi/master/install.sh | bash ``` -### 2. Configure +**Windows (PowerShell):** +```powershell +irm https://raw.githubusercontent.com/MhankBarBar/zero-ichi/master/install.ps1 | iex +``` -Copy the example config and make it yours: +### Manual Install ```bash -cp config.json.example config.json +pip install uv +git clone https://github.com/MhankBarBar/zero-ichi +cd zero-ichi +uv sync +cp .env.example .env ``` -Then edit `config.json` (keep the `$schema` key at the top for editor IntelliSense). - -(Check the [Config Guide](https://zeroichi.mhankbarbar.dev/getting-started/configuration) for the nerdy details) - -### 3. Launch +### Launch ```bash uv run zero-ichi diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts index 5590bb2..d4d5bc2 100644 --- a/docs/.vitepress/config.mts +++ b/docs/.vitepress/config.mts @@ -9,9 +9,16 @@ export default defineConfig({ ['link', { rel: 'icon', href: '/logo.png' }], ['link', { rel: 'preconnect', href: 'https://fonts.googleapis.com' }], ['link', { rel: 'preconnect', href: 'https://fonts.gstatic.com', crossorigin: '' }], - ['link', { href: 'https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600&display=swap', rel: 'stylesheet' }], + ['link', { href: 'https://fonts.googleapis.com/css2?family=Press+Start+2P&family=VT323&family=IBM+Plex+Mono:wght@400;500;600&display=swap', rel: 'stylesheet' }], ], + markdown: { + theme: { + light: 'github-dark', + dark: 'github-dark', + }, + }, + themeConfig: { logo: '/logo.png', diff --git a/docs/.vitepress/theme/custom.css b/docs/.vitepress/theme/custom.css index 272d298..aa8fa4c 100644 --- a/docs/.vitepress/theme/custom.css +++ b/docs/.vitepress/theme/custom.css @@ -1,170 +1,319 @@ /** * Custom theme overrides for Zero Ichi docs. - * Aesthetic: Tech Heavy (WhatsApp Green Edition) + * Aesthetic: Retro / CRT Terminal */ /* ── Fonts & Colors ──────────────────────────────────────── */ :root { - --vp-font-family-base: 'Inter', sans-serif; - --vp-font-family-mono: 'JetBrains Mono', monospace; + --vp-font-family-base: 'VT323', 'IBM Plex Mono', monospace; + --vp-font-family-mono: 'IBM Plex Mono', 'VT323', monospace; + --retro-heading: 'Press Start 2P', 'VT323', monospace; - /* Common Brand Colors */ - --vp-c-brand-1: #25d366; - /* WhatsApp Green */ - --vp-c-brand-2: #128c7e; - /* Teal Green */ - --vp-c-brand-3: #075e54; - /* Dark Teal */ - --vp-c-brand-soft: rgba(37, 211, 102, 0.1); + /* Retro Amber Palette */ + --vp-c-brand-1: #ffb000; + --vp-c-brand-2: #cc8d00; + --vp-c-brand-3: #ff6600; + --vp-c-brand-soft: rgba(255, 176, 0, 0.08); - /* Light Mode Defaults */ - --vp-c-bg: #ffffff; - --vp-c-bg-alt: #f0f2f5; - /* WhatsApp Chat BG-ish */ - --vp-c-bg-soft: #f8f9fa; + /* Light Mode — still retro-tinted */ + --vp-c-bg: #1a1a2e; + --vp-c-bg-alt: #16213e; + --vp-c-bg-soft: #0f3460; - --vp-c-text-1: #111827; - --vp-c-text-2: #4b5563; + --vp-c-text-1: #e0e0e0; + --vp-c-text-2: #a0a0a0; - --vp-c-border: #e5e7eb; - --vp-c-divider: #e5e7eb; + --vp-c-border: #33415c; + --vp-c-divider: #33415c; - --tech-grid-color: rgba(0, 0, 0, 0.05); + --retro-glow: #ffb000; + --retro-glow-soft: rgba(255, 176, 0, 0.3); + --retro-green: #33ff33; + --retro-scanline: rgba(0, 0, 0, 0.08); } .dark { - /* Dark Mode Overrides */ - --vp-c-bg: #09090b; - --vp-c-bg-alt: #121215; - --vp-c-bg-soft: #18181b; + --vp-c-bg: #0a0a0f; + --vp-c-bg-alt: #0f0f18; + --vp-c-bg-soft: #141420; - --vp-c-text-1: #fafafa; - --vp-c-text-2: #a1a1aa; + --vp-c-text-1: #e8e8e8; + --vp-c-text-2: #888; - --vp-c-border: #27272a; - --vp-c-divider: #27272a; + --vp-c-border: #222233; + --vp-c-divider: #222233; - --tech-grid-color: rgba(37, 211, 102, 0.05); + --retro-scanline: rgba(0, 0, 0, 0.12); } -/* ── Global Tech Grid Background ─────────────────────────── */ +/* ── CRT Scanline Overlay ────────────────────────────────── */ +body::after { + content: ''; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + pointer-events: none; + z-index: 9999; + background: repeating-linear-gradient(0deg, + var(--retro-scanline) 0px, + var(--retro-scanline) 1px, + transparent 1px, + transparent 3px); + opacity: 0.4; +} + +/* ── Global Background ───────────────────────────────────── */ body { background-color: var(--vp-c-bg); background-image: - linear-gradient(var(--tech-grid-color) 1px, transparent 1px), - linear-gradient(90deg, var(--tech-grid-color) 1px, transparent 1px); - background-size: 40px 40px; + radial-gradient(circle at 20% 50%, rgba(255, 176, 0, 0.03) 0%, transparent 50%), + radial-gradient(circle at 80% 50%, rgba(51, 255, 51, 0.02) 0%, transparent 50%); +} + +/* ── Keyframe Animations ─────────────────────────────────── */ +@keyframes blink-cursor { + + 0%, + 100% { + opacity: 1; + } + + 50% { + opacity: 0; + } +} + +@keyframes glow-pulse { + + 0%, + 100% { + text-shadow: 0 0 4px var(--retro-glow-soft); + } + + 50% { + text-shadow: 0 0 12px var(--retro-glow), 0 0 24px var(--retro-glow-soft); + } +} + +@keyframes subtle-flicker { + + 0%, + 100% { + opacity: 1; + } + + 92% { + opacity: 1; + } + + 93% { + opacity: 0.8; + } + + 94% { + opacity: 1; + } + + 96% { + opacity: 0.9; + } + + 97% { + opacity: 1; + } +} + +@keyframes border-glow { + + 0%, + 100% { + border-color: var(--vp-c-border); + } + + 50% { + border-color: var(--retro-glow); + } } /* ── Hero Section ────────────────────────────────────────── */ .VPHero .name { - font-family: var(--vp-font-family-mono); - font-weight: 800; - letter-spacing: -0.03em; - background: linear-gradient(120deg, var(--vp-c-brand-3) 0%, var(--vp-c-brand-1) 100%); - -webkit-background-clip: text; - background-clip: text; - -webkit-text-fill-color: transparent; + font-family: var(--retro-heading) !important; + font-weight: 400; + letter-spacing: 0.02em; + color: var(--retro-glow) !important; + background: none !important; + -webkit-text-fill-color: var(--retro-glow) !important; + text-shadow: + 0 0 7px var(--retro-glow), + 0 0 20px var(--retro-glow-soft), + 0 0 42px rgba(255, 176, 0, 0.15); + animation: subtle-flicker 8s infinite; +} + +.VPHero .clip { + -webkit-text-fill-color: var(--retro-glow) !important; + background: none !important; } .dark .VPHero .name { - background: linear-gradient(120deg, #fff 0%, #a1a1aa 100%); - -webkit-background-clip: text; - background-clip: text; - -webkit-text-fill-color: transparent; + color: var(--retro-glow) !important; + -webkit-text-fill-color: var(--retro-glow) !important; + background: none !important; + text-shadow: + 0 0 10px var(--retro-glow), + 0 0 30px var(--retro-glow-soft), + 0 0 60px rgba(255, 176, 0, 0.1); } .VPHero .text { - font-size: 2.5rem !important; - color: var(--vp-c-brand-1); - font-family: var(--vp-font-family-mono); - opacity: 0.9; + font-size: 2rem !important; + color: var(--retro-green) !important; + font-family: var(--retro-heading) !important; + text-shadow: 0 0 8px rgba(51, 255, 51, 0.5); + opacity: 0.95; } .VPHero .tagline { font-family: var(--vp-font-family-base); color: var(--vp-c-text-2); + font-size: 1.3rem; + line-height: 1.6; +} + +.VPHero .tagline::after { + content: '█'; + animation: blink-cursor 1s step-end infinite; + color: var(--retro-glow); + margin-left: 4px; +} + +.VPHero .image-container { + position: relative; } .VPHero .image-container::after { - /* Technical glow behind logo */ content: ''; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); - width: 200px; - height: 200px; - background: var(--vp-c-brand-1); - filter: blur(80px); - opacity: 0.15; + width: 240px; + height: 240px; + background: var(--retro-glow); + filter: blur(100px); + opacity: 0.12; z-index: -1; + border-radius: 50%; } -/* ── Feature Cards (Industrial Look) ─────────────────────── */ +/* ── Feature Cards (Retro Boxy) ──────────────────────────── */ .VPFeature { background: var(--vp-c-bg-alt) !important; border: 1px solid var(--vp-c-border) !important; - border-radius: 4px !important; - /* Sharper corners */ - transition: all 0.2s ease !important; + border-radius: 0 !important; + transition: all 0.25s ease !important; position: relative; overflow: hidden; } .VPFeature:hover { - border-color: var(--vp-c-brand-1) !important; - transform: translateY(-2px); - box-shadow: 0 4px 20px -10px rgba(37, 211, 102, 0.2); + border-color: var(--retro-glow) !important; + transform: none; + box-shadow: + 0 0 8px rgba(255, 176, 0, 0.15), + inset 0 0 20px rgba(255, 176, 0, 0.03); } -/* Tech accent line */ +/* Retro accent — top border lights up */ .VPFeature::before { content: ''; position: absolute; top: 0; left: 0; - width: 2px; - height: 0; - background: var(--vp-c-brand-1); - transition: height 0.3s ease; + width: 100%; + height: 2px; + background: linear-gradient(90deg, transparent, var(--retro-glow), transparent); + opacity: 0; + transition: opacity 0.3s ease; } .VPFeature:hover::before { - height: 100%; + opacity: 1; } .VPFeature .title { + font-family: var(--retro-heading) !important; + font-size: 0.7rem !important; + letter-spacing: 0.02em; + line-height: 1.6 !important; + color: var(--retro-glow); +} + +.VPFeature .details { + font-family: var(--vp-font-family-base); + font-size: 1.1rem; + line-height: 1.5; +} + +.VPFeature .link-text { font-family: var(--vp-font-family-mono); - letter-spacing: -0.02em; + font-size: 0.95rem; + color: var(--retro-glow) !important; +} + +.VPFeature .link-text::before { + content: '> '; + color: var(--retro-green); } /* ── Code Blocks (Terminal Style) ────────────────────────── */ .vp-doc div[class*='language-'] { - border-radius: 4px; + border-radius: 0; border: 1px solid var(--vp-c-border); - background-color: var(--vp-c-bg-alt) !important; + background-color: #0a0a0a !important; +} + +.vp-doc div[class*='language-'] pre, +.vp-doc div[class*='language-'] code { + color: #e8e8e8 !important; +} + +.vp-doc div[class*='language-']::before { + font-family: var(--retro-heading) !important; + font-size: 0.5rem; } .dark .vp-doc div[class*='language-'] { - background-color: #0d0d0d !important; + background-color: #060608 !important; + border-color: #1a1a2a; } .vp-doc code { font-family: var(--vp-font-family-mono) !important; - font-size: 0.9em; + font-size: 0.95em; +} + +.vp-doc :not(pre)>code { + background-color: rgba(255, 176, 0, 0.1) !important; + color: var(--retro-glow) !important; + border-radius: 0; + padding: 2px 6px; + border: 1px solid rgba(255, 176, 0, 0.2); } /* ── Stats Section ───────────────────────────────────────── */ .stats-section { display: flex; justify-content: center; - gap: 2rem; + gap: 3rem; padding: 4rem 1rem; - border-top: 1px solid var(--vp-c-divider); - border-bottom: 1px solid var(--vp-c-divider); + border-top: 1px dashed var(--retro-glow); + border-bottom: 1px dashed var(--retro-glow); background: var(--vp-c-bg-alt); margin: 4rem 0; + position: relative; } .stat-item { @@ -172,73 +321,160 @@ body { } .stat-number { - font-family: var(--vp-font-family-mono); - font-size: 2.5rem; - font-weight: 700; - color: var(--vp-c-brand-1); + font-family: var(--retro-heading); + font-size: 1.8rem; + font-weight: 400; + color: var(--retro-glow); + text-shadow: 0 0 10px var(--retro-glow-soft); + animation: glow-pulse 3s ease-in-out infinite; } .stat-label { text-transform: uppercase; - font-size: 0.75rem; - letter-spacing: 0.1em; + font-family: var(--retro-heading); + font-size: 0.5rem; + letter-spacing: 0.15em; color: var(--vp-c-text-2); - margin-top: 0.5rem; + margin-top: 0.75rem; } /* ── Buttons ─────────────────────────────────────────────── */ .VPButton.brand { - border-radius: 4px !important; - background-color: var(--vp-c-brand-1) !important; - border: 1px solid var(--vp-c-brand-1) !important; - font-family: var(--vp-font-family-mono); - font-weight: 600; + border-radius: 0 !important; + background-color: transparent !important; + border: 2px solid var(--retro-glow) !important; + font-family: var(--retro-heading); + font-weight: 400; text-transform: uppercase; letter-spacing: 0.05em; - font-size: 0.9rem; + font-size: 0.65rem; + color: var(--retro-glow) !important; + padding: 12px 24px !important; + transition: all 0.2s ease; } .VPButton.brand:hover { - background-color: transparent !important; - color: var(--vp-c-brand-1) !important; + background-color: var(--retro-glow) !important; + color: #0a0a0f !important; + box-shadow: 0 0 15px var(--retro-glow-soft), 0 0 30px rgba(255, 176, 0, 0.1); } .VPButton.alt { - border-radius: 4px !important; - border-color: var(--vp-c-border) !important; - font-family: var(--vp-font-family-mono); - font-size: 0.9rem; + border-radius: 0 !important; + border: 2px solid var(--vp-c-text-2) !important; + font-family: var(--retro-heading); + font-size: 0.65rem; + text-transform: uppercase; + letter-spacing: 0.05em; + padding: 12px 24px !important; + transition: all 0.2s ease; + color: var(--vp-c-text-1) !important; + background-color: transparent !important; } .VPButton.alt:hover { - border-color: var(--vp-c-text-1) !important; + border-color: var(--retro-green) !important; + color: var(--retro-green) !important; + box-shadow: 0 0 10px rgba(51, 255, 51, 0.15); } /* ── Sidebar & Nav ───────────────────────────────────────── */ .VPSidebar { border-right: 1px solid var(--vp-c-border) !important; background-color: var(--vp-c-bg) !important; + font-family: var(--vp-font-family-base); +} + +.VPSidebar .group .text { + font-family: var(--retro-heading) !important; + font-size: 0.55rem !important; + letter-spacing: 0.05em; + text-transform: uppercase; } .VPNavBar { background-color: var(--vp-c-bg) !important; - /* Glass effect base */ border-bottom: 1px solid var(--vp-c-border) !important; - backdrop-filter: blur(10px); - opacity: 0.95; + backdrop-filter: none; +} + +.VPNavBar .title { + font-family: var(--retro-heading) !important; + font-size: 0.6rem !important; } .dark .VPNavBar { - background-color: rgba(9, 9, 11, 0.8) !important; + background-color: rgba(10, 10, 15, 0.95) !important; + border-bottom-color: #222233 !important; } -/* ── Step Cards (Process) ────────────────────────────────── */ +/* Active sidebar item glow */ +.VPSidebar a.active { + color: var(--retro-glow) !important; + text-shadow: 0 0 6px var(--retro-glow-soft); +} + +/* Nav links */ +.VPNavBar .VPNavBarMenuLink .VPLink, +.VPNavBar a { + font-family: var(--vp-font-family-base); + font-size: 1.1rem; +} + +/* ── Content Typography ──────────────────────────────────── */ +.vp-doc h1 { + font-family: var(--retro-heading) !important; + font-size: 1.2rem !important; + color: var(--retro-glow); + text-shadow: 0 0 6px var(--retro-glow-soft); + line-height: 1.8 !important; + border-bottom: 1px dashed var(--vp-c-border); + padding-bottom: 1rem; +} + +.vp-doc h2 { + font-family: var(--retro-heading) !important; + font-size: 0.85rem !important; + color: var(--retro-glow); + border-top: 1px dashed var(--vp-c-border); + padding-top: 1.5rem; + line-height: 1.8 !important; +} + +.vp-doc h3 { + font-family: var(--retro-heading) !important; + font-size: 0.7rem !important; + color: var(--retro-green); + line-height: 1.8 !important; +} + +.vp-doc p, +.vp-doc li { + font-family: var(--vp-font-family-base); + font-size: 1.15rem; + line-height: 1.7; +} + +/* ── Step Cards (Retro Process) ──────────────────────────── */ .home-section { max-width: 960px; margin: 0 auto; padding: 0 1.5rem 4rem; } +.home-section h2 { + font-family: var(--retro-heading) !important; + font-size: 0.85rem; + color: var(--retro-glow); + text-shadow: 0 0 8px var(--retro-glow-soft); +} + +.home-section .subtitle { + font-family: var(--vp-font-family-base); + color: var(--vp-c-text-2); + font-size: 1.15rem; +} + .quick-steps { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); @@ -249,34 +485,64 @@ body { .step-card { background: var(--vp-c-bg-alt); border: 1px solid var(--vp-c-border); + border-radius: 0; padding: 1.5rem; - transition: all 0.2s; + transition: all 0.25s; + position: relative; } .step-card:hover { - border-color: var(--vp-c-text-2); + border-color: var(--retro-glow); + box-shadow: 0 0 8px rgba(255, 176, 0, 0.1); +} + +.step-card::after { + content: ''; + position: absolute; + bottom: 0; + left: 0; + width: 100%; + height: 1px; + background: linear-gradient(90deg, transparent, var(--retro-glow), transparent); + opacity: 0; + transition: opacity 0.3s; +} + +.step-card:hover::after { + opacity: 1; } .step-number { - font-family: var(--vp-font-family-mono); - color: var(--vp-c-brand-1); - font-size: 1.25rem; - font-weight: 700; - margin-bottom: 0.5rem; + font-family: var(--retro-heading); + color: var(--retro-glow); + font-size: 0.8rem; + font-weight: 400; + margin-bottom: 0.75rem; display: block; + text-shadow: 0 0 6px var(--retro-glow-soft); +} + +.step-number::before { + content: '// '; + color: var(--vp-c-text-2); } .step-card h3 { margin: 0; - font-size: 1rem; - font-weight: 600; + font-family: var(--retro-heading) !important; + font-size: 0.6rem; + font-weight: 400; color: var(--vp-c-text-1); + text-transform: uppercase; + letter-spacing: 0.05em; + line-height: 1.6; } .step-card p { color: var(--vp-c-text-2); - font-size: 0.9rem; + font-size: 1.05rem; line-height: 1.5; + font-family: var(--vp-font-family-base); } /* ── Command Categories ──────────────────────────────────── */ @@ -290,28 +556,36 @@ body { .category-chip { display: inline-flex; align-items: center; - padding: 0.5rem 1rem; - background: var(--vp-c-bg-alt); + padding: 0.6rem 1.2rem; + background: transparent; border: 1px solid var(--vp-c-border); - border-radius: 4px; - font-family: var(--vp-font-family-mono); - font-size: 0.85rem; + border-radius: 0; + font-family: var(--retro-heading); + font-size: 0.5rem; color: var(--vp-c-text-2) !important; text-decoration: none !important; + text-transform: uppercase; + letter-spacing: 0.08em; transition: all 0.2s; } .category-chip:hover { - color: var(--vp-c-brand-1) !important; - border-color: var(--vp-c-brand-1); - background: var(--vp-c-brand-soft); - transform: translateY(-1px); + color: var(--retro-glow) !important; + border-color: var(--retro-glow); + background: rgba(255, 176, 0, 0.05); + box-shadow: 0 0 8px rgba(255, 176, 0, 0.1); +} + +/* ── Footer ──────────────────────────────────────────────── */ +.VPFooter { + border-top: 1px dashed var(--vp-c-border) !important; + font-family: var(--vp-font-family-base); } /* ── Scrollbars ──────────────────────────────────────────── */ ::-webkit-scrollbar { - width: 8px; - height: 8px; + width: 6px; + height: 6px; } ::-webkit-scrollbar-track { @@ -320,9 +594,352 @@ body { ::-webkit-scrollbar-thumb { background: var(--vp-c-border); - border-radius: 4px; + border-radius: 0; } ::-webkit-scrollbar-thumb:hover { - background: var(--vp-c-text-2); + background: var(--retro-glow); +} + +/* ── Tables (Retro) ──────────────────────────────────────── */ +.vp-doc table { + border-collapse: collapse; + border: 1px solid var(--vp-c-border); +} + +.vp-doc th { + font-family: var(--retro-heading); + font-size: 0.55rem; + text-transform: uppercase; + letter-spacing: 0.05em; + background: var(--vp-c-bg-alt); + color: var(--retro-glow); +} + +.vp-doc td { + border: 1px solid var(--vp-c-border); + font-family: var(--vp-font-family-base); +} + +/* ── Blockquotes / Tips / Warnings ───────────────────────── */ +.vp-doc .custom-block { + border-radius: 0; + border-left: 3px solid var(--retro-glow); +} + +.vp-doc .custom-block.tip { + border-left-color: var(--retro-green); +} + +.vp-doc .custom-block .custom-block-title { + font-family: var(--retro-heading); + font-size: 0.55rem; + letter-spacing: 0.05em; +} + +/* ── Search ──────────────────────────────────────────────── */ +.VPLocalSearchBox .shell { + border-radius: 0 !important; + border: 1px solid var(--retro-glow) !important; +} + +/* ── Misc Overrides ──────────────────────────────────────── */ +.VPDoc .container .content { + font-family: var(--vp-font-family-base); +} + +/* ── Terminal Window Frames (CSS-only) ───────────────────── */ +.terminal-window { + border: 1px solid var(--vp-c-border); + background: var(--vp-c-bg-alt); + margin: 2rem auto; + max-width: 960px; + overflow: hidden; + position: relative; + padding: 52px 1.5rem 1.5rem; +} + +/* Titlebar via ::before */ +.terminal-window::before { + content: '● ● ● ' attr(data-title); + display: block; + position: absolute; + top: 0; + left: 0; + right: 0; + padding: 8px 14px; + background: rgba(0, 0, 0, 0.3); + border-bottom: 1px solid var(--vp-c-border); + font-family: var(--vp-font-family-mono); + font-size: 0.85rem; + color: var(--vp-c-text-2); +} + +/* Stats inside terminal: remove old borders */ +.terminal-window .stats-section { + border: none; + margin: 0; + padding: 1rem 0; + background: transparent; +} + +/* Subtitle as terminal prompt */ +.terminal-window .subtitle { + font-family: var(--vp-font-family-mono); + color: var(--retro-green); + font-size: 1rem; + margin: 0.25rem 0 1rem; +} + +/* Terminal window headings */ +.terminal-window h2 { + font-family: var(--retro-heading) !important; + font-size: 0.8rem; + color: var(--retro-glow); + text-shadow: 0 0 8px var(--retro-glow-soft); + margin: 0 0 0.5rem; + border: none; + padding: 0; +} + +/* Category chips as directory listings */ +.terminal-window .category-chip { + color: var(--retro-green) !important; + border-color: transparent; + background: transparent; + padding: 0.4rem 0.8rem; +} + +.terminal-window .category-chip:hover { + color: var(--retro-glow) !important; + border-color: var(--retro-glow); + background: rgba(255, 176, 0, 0.05); +} + +/* ── Light Mode (Retro Amber Terminal) ───────────────────── */ +html:not(.dark) { + --vp-c-bg: #fdf6e3; + --vp-c-bg-alt: #f5eedc; + --vp-c-bg-soft: #eee8d5; + + --vp-c-text-1: #3c3836; + --vp-c-text-2: #665c54; + + --vp-c-border: #d5c4a1; + --vp-c-divider: #d5c4a1; + + --retro-glow: #b57614; + --retro-glow-soft: rgba(181, 118, 20, 0.3); + --retro-green: #427b58; + --retro-scanline: rgba(0, 0, 0, 0.03); +} + +/* Light mode hero overrides */ +html:not(.dark) .VPHero .name { + color: #b57614 !important; + -webkit-text-fill-color: #b57614 !important; + text-shadow: none; +} + +html:not(.dark) .VPHero .text { + color: #427b58 !important; + text-shadow: none; +} + +html:not(.dark) .VPButton.brand { + border-color: #b57614 !important; + color: #b57614 !important; +} + +html:not(.dark) .VPButton.brand:hover { + background-color: #b57614 !important; + color: #fdf6e3 !important; +} + +html:not(.dark) .VPButton.alt { + border-color: #665c54 !important; + color: #3c3836 !important; +} + +html:not(.dark) .VPButton.alt:hover { + border-color: #427b58 !important; + color: #427b58 !important; +} + +html:not(.dark) .stat-number { + color: #b57614; + text-shadow: none; +} + +html:not(.dark) .VPFeature .title { + color: #b57614; +} + +html:not(.dark) .VPFeature:hover { + border-color: #b57614 !important; + box-shadow: 0 0 8px rgba(181, 118, 20, 0.1); +} + +html:not(.dark) .vp-doc :not(pre)>code { + background-color: rgba(181, 118, 20, 0.1) !important; + color: #b57614 !important; + border-color: rgba(181, 118, 20, 0.2); +} + +html:not(.dark) .vp-doc h1, +html:not(.dark) .vp-doc h2 { + color: #b57614; + text-shadow: none; +} + +html:not(.dark) .vp-doc h3 { + color: #427b58; +} + +html:not(.dark) .terminal-window::before { + background: rgba(0, 0, 0, 0.06); +} + +html:not(.dark) .terminal-window .subtitle { + color: #427b58; +} + +html:not(.dark) body::after { + opacity: 0.15; +} + +html:not(.dark) body { + background-image: none; +} + +/* Light mode code blocks — warm sepia terminal */ +html:not(.dark) .vp-doc div[class*='language-'] { + background-color: #2d2418 !important; + border: 1px solid #5c4a32 !important; +} + +/* Code block language label */ +html:not(.dark) .vp-doc div[class*='language-']::before { + color: #a08060 !important; +} + +/* Line numbers in light mode */ +html:not(.dark) .vp-doc div[class*='language-'] .line-numbers { + color: #7a6545; + border-right-color: #5c4a32; +} + +/* ── Mobile Responsive ───────────────────────────────────── */ +@media (max-width: 768px) { + + /* Hero title scaling */ + .VPHero .name { + font-size: 1.8rem !important; + } + + .VPHero .text { + font-size: 1.4rem !important; + } + + .VPHero .tagline { + font-size: 1rem !important; + } + + /* Terminal windows — tighter padding on mobile */ + .terminal-window { + margin: 1rem 0.5rem; + padding: 44px 1rem 1rem; + } + + .terminal-window::before { + padding: 6px 10px; + font-size: 0.75rem; + } + + /* Terminal headings smaller on mobile */ + .terminal-window h2 { + font-size: 0.65rem; + } + + .terminal-window .subtitle { + font-size: 0.9rem; + } + + /* Stats — keep 3-col but smaller fonts */ + .stats-section { + gap: 0.5rem !important; + padding: 1rem 0 !important; + } + + .stat-number { + font-size: 2rem !important; + } + + .stat-label { + font-size: 0.7rem !important; + } + + /* Step cards — stack vertically */ + .quick-steps { + grid-template-columns: 1fr !important; + gap: 0.75rem !important; + } + + .step-card { + padding: 1rem !important; + } + + .step-card h3 { + font-size: 0.6rem !important; + } + + /* Category chips — wrap properly */ + .categories-grid { + gap: 0.5rem !important; + } + + .category-chip { + font-size: 0.6rem !important; + padding: 0.3rem 0.5rem !important; + } + + /* Home sections — less margin */ + .home-section { + margin: 1rem 0; + padding: 0; + } + + /* Feature cards */ + .VPFeature .title { + font-size: 0.6rem !important; + } + + /* Buttons */ + .VPButton { + font-size: 0.6rem !important; + padding: 0.6rem 1.2rem !important; + } +} + +@media (max-width: 480px) { + .VPHero .name { + font-size: 1.4rem !important; + } + + .VPHero .text { + font-size: 1.1rem !important; + } + + .terminal-window { + margin: 0.75rem 0; + padding: 40px 0.75rem 0.75rem; + } + + .stat-number { + font-size: 1.6rem !important; + } + + .categories-grid { + grid-template-columns: repeat(2, 1fr) !important; + } } \ No newline at end of file diff --git a/docs/getting-started/installation.md b/docs/getting-started/installation.md index edc1d95..705caca 100644 --- a/docs/getting-started/installation.md +++ b/docs/getting-started/installation.md @@ -1,5 +1,28 @@ # Installation +## One-Line Install + +The fastest way to get started. This auto-installs all dependencies, clones the repo, and sets up your environment. + +**Linux / macOS:** +```bash +curl -fsSL https://raw.githubusercontent.com/MhankBarBar/zero-ichi/master/install.sh | bash +``` + +**Windows (PowerShell):** +```powershell +irm https://raw.githubusercontent.com/MhankBarBar/zero-ichi/master/install.ps1 | iex +``` + +::: tip Custom Install Directory +Set `INSTALL_DIR` to change the install location (defaults to `~/zero-ichi`): +```bash +INSTALL_DIR=/opt/zero-ichi curl -fsSL https://raw.githubusercontent.com/MhankBarBar/zero-ichi/master/install.sh | bash +``` +::: + +--- + ## Requirements - **Python 3.11+** @@ -8,7 +31,7 @@ - **[Bun](https://bun.sh)** — required for YouTube JS challenge solving (yt-dlp) - **Node.js 20+** — for the web dashboard (optional) -## Quick Start +## Manual Install ```bash # Install uv (if not already installed) diff --git a/docs/index.md b/docs/index.md index 5a79ba8..4ca23d6 100644 --- a/docs/index.md +++ b/docs/index.md @@ -61,57 +61,66 @@ features: linkText: Read guide --- +
-
-
60+
-
Commands
-
-
-
9
-
Categories
-
-
-
2
-
Languages
-
+
+
60+
+
Commands
+
+
+
9
+
Categories
+
+
+
2
+
Languages
+
+
-

Quick Start

-

Get your bot running in 3 steps

+
+

Quick Start

+

$ echo "Get your bot running in under a minute"

+ +

Linux / macOS

+ +```bash +curl -fsSL https://raw.githubusercontent.com/MhankBarBar/zero-ichi/master/install.sh | bash +``` + +

Windows (PowerShell)

+ +```powershell +irm https://raw.githubusercontent.com/MhankBarBar/zero-ichi/master/install.ps1 | iex +``` -
-
-
1
-

Install

-

Clone the repo and install dependencies with uv sync

-
-
-
2
-

Configure

-

Edit config.json and set your prefix, owner number, and API keys

-
-
-
3
-

Run

-

Start with uv run zero-ichi and scan the QR code with WhatsApp

-
-
+

Then start the bot:

+ +```bash +uv run zero-ichi +``` + +See full installation guide → +
-

Command Categories

-

Everything you need, organized neatly

- - +
+

Command Categories

+

$ ls -la commands/

+ +
+
+ + diff --git a/install.ps1 b/install.ps1 new file mode 100644 index 0000000..a58021e --- /dev/null +++ b/install.ps1 @@ -0,0 +1,152 @@ +#Requires -Version 5.1 + +$ErrorActionPreference = "Stop" + +function Write-Info { Write-Host "[INFO] " -ForegroundColor Cyan -NoNewline; Write-Host $args } +function Write-Ok { Write-Host "[OK] " -ForegroundColor Green -NoNewline; Write-Host $args } +function Write-Warn { Write-Host "[WARN] " -ForegroundColor Yellow -NoNewline; Write-Host $args } +function Write-Fail { Write-Host "[FAIL] " -ForegroundColor Red -NoNewline; Write-Host $args; exit 1 } + +Write-Host "" +Write-Host "+==============================================+" -ForegroundColor White +Write-Host "| Zero Ichi Installer |" -ForegroundColor White +Write-Host "| WhatsApp Bot built with <3 |" -ForegroundColor White +Write-Host "+==============================================+" -ForegroundColor White +Write-Host "" + +$InstallDir = if ($env:INSTALL_DIR) { $env:INSTALL_DIR } else { Join-Path $HOME "zero-ichi" } +$RepoUrl = "https://github.com/MhankBarBar/zero-ichi.git" +$Branch = if ($env:BRANCH) { $env:BRANCH } else { "main" } + +function Test-Command { param($Name) return [bool](Get-Command $Name -ErrorAction SilentlyContinue) } + +function Update-Path { + $env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + + [System.Environment]::GetEnvironmentVariable("Path", "User") +} + +function Test-Python { + $pyCmd = $null + foreach ($cmd in @("python", "python3")) { + if (Test-Command $cmd) { + $ver = & $cmd -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')" 2>$null + if ($ver) { + $parts = $ver.Split(".") + if ([int]$parts[0] -ge 3 -and [int]$parts[1] -ge 11) { + $pyCmd = $cmd + break + } + } + } + } + if ($pyCmd) { + Write-Ok "Python $ver found ($pyCmd)" + } else { + Write-Fail "Python 3.11+ is required. Download from https://python.org" + } +} + +function Test-Uv { + if (Test-Command "uv") { + Write-Ok "uv found ($(uv --version))" + } else { + Write-Info "Installing uv..." + irm https://astral.sh/uv/install.ps1 | iex + Update-Path + if (Test-Command "uv") { + Write-Ok "uv installed ($(uv --version))" + } else { + Write-Fail "Failed to install uv. Install manually: https://docs.astral.sh/uv/" + } + } +} + +function Test-FFmpeg { + if (Test-Command "ffmpeg") { + Write-Ok "FFmpeg found" + } else { + if (Test-Command "winget") { + Write-Info "Installing FFmpeg via winget..." + winget install --id Gyan.FFmpeg -e --accept-source-agreements --accept-package-agreements --silent + Update-Path + if (Test-Command "ffmpeg") { + Write-Ok "FFmpeg installed" + } else { + Write-Warn "FFmpeg installed but not in PATH. Restart your terminal or add it to PATH manually." + } + } else { + Write-Warn "FFmpeg not found. Install it from https://ffmpeg.org or via: winget install Gyan.FFmpeg" + } + } +} + +function Test-Bun { + if (Test-Command "bun") { + Write-Ok "Bun found ($(bun --version))" + } else { + Write-Info "Installing Bun (needed for YouTube downloads)..." + irm https://bun.sh/install.ps1 | iex + Update-Path + if (Test-Command "bun") { + Write-Ok "Bun installed ($(bun --version))" + } else { + Write-Warn "Bun installation failed. YouTube downloads may not work." + } + } +} + +function Test-Git { + if (Test-Command "git") { + Write-Ok "Git found" + } else { + Write-Fail "Git is required. Install from https://git-scm.com or: winget install Git.Git" + } +} + +Write-Info "Checking dependencies..." +Write-Host "" +Test-Git +Test-Python +Test-Uv +Test-FFmpeg +Test-Bun +Write-Host "" + +if (Test-Path $InstallDir) { + Write-Info "Directory $InstallDir already exists, pulling latest..." + Push-Location $InstallDir + try { git pull --ff-only origin $Branch } catch { Write-Warn "Git pull failed, continuing with existing code." } +} else { + Write-Info "Cloning Zero Ichi to $InstallDir..." + git clone --depth 1 --branch $Branch $RepoUrl $InstallDir + Push-Location $InstallDir +} + +Write-Info "Installing Python dependencies..." +uv sync --quiet +Write-Ok "Dependencies installed" + +$envFile = Join-Path $InstallDir ".env" +$envExample = Join-Path $InstallDir ".env.example" +if (-not (Test-Path $envFile)) { + Copy-Item $envExample $envFile + Write-Ok "Created .env from .env.example" + Write-Warn "Edit $envFile to configure your bot." +} else { + Write-Ok ".env already exists, skipping." +} + +Pop-Location + +Write-Host "" +Write-Host "Installation complete!" -ForegroundColor Green +Write-Host "" +Write-Host " To start the bot:" -ForegroundColor White +Write-Host " cd $InstallDir" +Write-Host " uv run zero-ichi" +Write-Host "" +Write-Host " First run:" -ForegroundColor White +Write-Host " Scan the QR code with WhatsApp -> Settings -> Linked Devices" +Write-Host "" +Write-Host " Docs: https://zeroichi.mhankbarbar.dev" -ForegroundColor White +Write-Host "" diff --git a/install.sh b/install.sh new file mode 100644 index 0000000..06afb63 --- /dev/null +++ b/install.sh @@ -0,0 +1,148 @@ +#!/usr/bin/env bash +set -euo pipefail + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +CYAN='\033[0;36m' +BOLD='\033[1m' +RESET='\033[0m' + +info() { echo -e "${CYAN}[INFO]${RESET} $*"; } +ok() { echo -e "${GREEN}[OK]${RESET} $*"; } +warn() { echo -e "${YELLOW}[WARN]${RESET} $*"; } +fail() { echo -e "${RED}[FAIL]${RESET} $*"; exit 1; } + +echo "" +echo -e "${BOLD}╔══════════════════════════════════════╗${RESET}" +echo -e "${BOLD}║ Zero Ichi Installer ║${RESET}" +echo -e "${BOLD}║ WhatsApp Bot built with 💖 ║${RESET}" +echo -e "${BOLD}╚══════════════════════════════════════╝${RESET}" +echo "" + +INSTALL_DIR="${INSTALL_DIR:-$HOME/zero-ichi}" +REPO_URL="https://github.com/MhankBarBar/zero-ichi.git" +BRANCH="${BRANCH:-main}" + +OS="$(uname -s)" +case "$OS" in + Linux*) PLATFORM="linux";; + Darwin*) PLATFORM="macos";; + *) fail "Unsupported OS: $OS";; +esac +info "Detected platform: ${BOLD}$PLATFORM${RESET}" + +has() { command -v "$1" &>/dev/null; } + +check_python() { + if has python3; then + PY_VER=$(python3 -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')") + PY_MAJOR=$(echo "$PY_VER" | cut -d. -f1) + PY_MINOR=$(echo "$PY_VER" | cut -d. -f2) + if [ "$PY_MAJOR" -ge 3 ] && [ "$PY_MINOR" -ge 11 ]; then + ok "Python $PY_VER found" + return + fi + fi + fail "Python 3.11+ is required. Install it from https://python.org or your package manager." +} + +check_uv() { + if has uv; then + ok "uv found ($(uv --version))" + else + info "Installing uv..." + curl -LsSf https://astral.sh/uv/install.sh | sh + export PATH="$HOME/.local/bin:$PATH" + if has uv; then + ok "uv installed ($(uv --version))" + else + fail "Failed to install uv. Install manually: https://docs.astral.sh/uv/" + fi + fi +} + +check_ffmpeg() { + if has ffmpeg; then + ok "FFmpeg found" + else + warn "FFmpeg not found. Attempting to install..." + if [ "$PLATFORM" = "linux" ]; then + if has apt-get; then + sudo apt-get update -qq && sudo apt-get install -y -qq ffmpeg + elif has dnf; then + sudo dnf install -y ffmpeg + elif has pacman; then + sudo pacman -S --noconfirm ffmpeg + else + fail "Cannot auto-install FFmpeg. Install it manually." + fi + elif [ "$PLATFORM" = "macos" ]; then + if has brew; then + brew install ffmpeg + else + fail "Homebrew not found. Install FFmpeg manually: brew install ffmpeg" + fi + fi + has ffmpeg && ok "FFmpeg installed" || fail "FFmpeg installation failed." + fi +} + +check_bun() { + if has bun; then + ok "Bun found ($(bun --version))" + else + info "Installing Bun (needed for YouTube downloads)..." + curl -fsSL https://bun.sh/install | bash + export PATH="$HOME/.bun/bin:$PATH" + has bun && ok "Bun installed ($(bun --version))" || warn "Bun installation failed. YouTube downloads may not work." + fi +} + +check_git() { + has git && ok "Git found" || fail "Git is required. Install it from https://git-scm.com" +} + +info "Checking dependencies..." +echo "" +check_git +check_python +check_uv +check_ffmpeg +check_bun +echo "" + +if [ -d "$INSTALL_DIR" ]; then + info "Directory $INSTALL_DIR already exists, pulling latest..." + cd "$INSTALL_DIR" + git pull --ff-only origin "$BRANCH" || warn "Git pull failed, continuing with existing code." +else + info "Cloning Zero Ichi to $INSTALL_DIR..." + git clone --depth 1 --branch "$BRANCH" "$REPO_URL" "$INSTALL_DIR" + cd "$INSTALL_DIR" +fi + +info "Installing Python dependencies..." +uv sync --quiet +ok "Dependencies installed" + +if [ ! -f .env ]; then + cp .env.example .env + ok "Created .env from .env.example" + warn "Edit ${BOLD}$INSTALL_DIR/.env${RESET} to configure your bot." +else + ok ".env already exists, skipping." +fi + +echo "" +echo -e "${GREEN}${BOLD}✅ Installation complete!${RESET}" +echo "" +echo -e " ${BOLD}To start the bot:${RESET}" +echo -e " cd $INSTALL_DIR" +echo -e " uv run zero-ichi" +echo "" +echo -e " ${BOLD}First run:${RESET}" +echo -e " Scan the QR code with WhatsApp → Settings → Linked Devices" +echo "" +echo -e " ${BOLD}Docs:${RESET} https://zeroichi.mhankbarbar.dev" +echo "" diff --git a/pyproject.toml b/pyproject.toml index 20e6f6f..83e7c99 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,7 +18,7 @@ dependencies = [ "apscheduler>=3.10.0", "pydantic-ai>=1.48.0", "python-dotenv>=1.2.1", - "yt-dlp>=2026.2.21", + "yt-dlp>=2026.03.03", "gallery-dl>=1.31.7", "Pillow>=10.0.0", ] diff --git a/uv.lock b/uv.lock index 1ae0015..a840a8a 100644 --- a/uv.lock +++ b/uv.lock @@ -3670,11 +3670,11 @@ wheels = [ [[package]] name = "yt-dlp" -version = "2026.2.21" +version = "2026.3.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/58/d9/55ffff25204733e94a507552ad984d5a8a8e4f9d1f0d91763e6b1a41c79b/yt_dlp-2026.2.21.tar.gz", hash = "sha256:4407dfc1a71fec0dee5ef916a8d4b66057812939b509ae45451fa8fb4376b539", size = 3116630, upload-time = "2026-02-21T20:40:53.522Z" } +sdist = { url = "https://files.pythonhosted.org/packages/66/6f/7427d23609353e5ef3470ff43ef551b8bd7b166dd4fef48957f0d0e040fe/yt_dlp-2026.3.3.tar.gz", hash = "sha256:3db7969e3a8964dc786bdebcffa2653f31123bf2a630f04a17bdafb7bbd39952", size = 3118658, upload-time = "2026-03-03T16:54:53.909Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5a/40/664c99ee36d80d84ce7a96cd98aebcb3d16c19e6c3ad3461d2cf5424040e/yt_dlp-2026.2.21-py3-none-any.whl", hash = "sha256:0d8408f5b6d20487f5caeb946dfd04f9bcd2f1a3a125b744a0a982b590e449f7", size = 3313392, upload-time = "2026-02-21T20:40:51.514Z" }, + { url = "https://files.pythonhosted.org/packages/7e/a4/8b5cd28ab87aef48ef15e74241befec3445496327db028f34147a9e0f14f/yt_dlp-2026.3.3-py3-none-any.whl", hash = "sha256:166c6e68c49ba526474bd400e0129f58aa522c2896204aa73be669c3d2f15e63", size = 3315599, upload-time = "2026-03-03T16:54:51.899Z" }, ] [[package]] @@ -3714,7 +3714,7 @@ requires-dist = [ { name = "rich", specifier = ">=13.0" }, { name = "uvicorn", specifier = ">=0.34.0" }, { name = "watchfiles", specifier = ">=1.1.1" }, - { name = "yt-dlp", specifier = ">=2026.2.21" }, + { name = "yt-dlp", specifier = ">=2026.3.3" }, ] [package.metadata.requires-dev]